browsertime 23.4.0 → 23.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Browsertime changelog (we do [semantic versioning](https://semver.org))
2
2
 
3
+ ## 23.4.2 - 2024-12-10
4
+ ### Fixed
5
+ * Improve how we compute the power consumption numbers from the Firefox Profiler output PR by [Nazım Can Altınova](https://github.com/canova) [#2220](https://github.com/sitespeedio/browsertime/pull/2220)
6
+
7
+ ## 23.4.1 - 2024-11-23
8
+ ### Fixed
9
+ * Cleanup of the extra timings that is added to the timeline for Chrome [#2218](https://github.com/sitespeedio/browsertime/pull/2218)
10
+
3
11
  ## 23.4.0 - 2024-11-22
4
12
 
5
13
  ### Added
@@ -15,7 +23,7 @@ Andy Davies](https://github.com/andydavies) cool [https://github.com/andydavies/
15
23
  ### Fixed
16
24
  * Disable search suggestion requests for Firefox [#2215](https://github.com/sitespeedio/browsertime/pull/2215)
17
25
  * Fix for including HTTP requests in the Firefox profile [#2214](https://github.com/sitespeedio/browsertime/pull/2214).
18
- * Fix when running --enabkleProfileRun and get visual metrics. It used to generate an error log, this fixes that [#2213](https://github.com/sitespeedio/browsertime/pull/2213).
26
+ * Fix when running --enableProfileRun and get visual metrics. It used to generate an error log, this fixes that [#2213](https://github.com/sitespeedio/browsertime/pull/2213).
19
27
 
20
28
  ## 23.3.2 - 2024-11-21
21
29
  ### Fixed
@@ -3,7 +3,7 @@
3
3
  export const elementTimeLine = `
4
4
  (function () {
5
5
  const observer = new PerformanceObserver(list => { });
6
- observer.observe({ type: 'element', buffered: true, includeSoftNavigationObservations: true });
6
+ observer.observe({ type: 'element', buffered: true });
7
7
  const entries = observer.takeRecords();
8
8
  for (let entry of entries) {
9
9
  performance.mark(entry.identifier, {
@@ -3,7 +3,7 @@
3
3
  export const fcpTimeLine = `
4
4
  (function () {
5
5
  const observer = new PerformanceObserver(list => { });
6
- observer.observe({ type: 'paint', buffered: true, includeSoftNavigationObservations: true });
6
+ observer.observe({ type: 'paint', buffered: true });
7
7
  const entries = observer.takeRecords();
8
8
  for (let entry of entries) {
9
9
  performance.mark(entry.name === 'first-contentful-paint' ? 'FCP': 'FP', {
@@ -5,7 +5,7 @@ export const inpTimeLine = `
5
5
  (function() {
6
6
  const observer = new PerformanceObserver(list => {});
7
7
  for (const type of ['event']) {
8
- observer.observe({ type, buffered: true, durationThreshold: 0, includeSoftNavigationObservations: true });
8
+ observer.observe({ type, buffered: true, durationThreshold: 0});
9
9
  }
10
10
  let inpEventCount = 0;
11
11
  const entries = observer.takeRecords();
@@ -3,7 +3,7 @@
3
3
  export const lcpTimeLine = `
4
4
  (function () {
5
5
  const observer = new PerformanceObserver(list => { });
6
- observer.observe({ type: 'largest-contentful-paint', buffered: true, durationThreshold: 0, includeSoftNavigationObservations: true });
6
+ observer.observe({ type: 'largest-contentful-paint', buffered: true });
7
7
  const entries = observer.takeRecords();
8
8
  entries.forEach((entry, index) => {
9
9
  if (index === entries.length - 1) {
@@ -16,11 +16,11 @@ export const lcpTimeLine = `
16
16
  track: 'Metrics',
17
17
  trackGroup: 'Browsertime Timeline',
18
18
  color: 'primary-dark',
19
- tooltipText: 'LCP ' + entry.element ? entry.element.className : '',
19
+ tooltipText: 'LCP ' + (entry.element?.tagName || ''),
20
20
  properties: [
21
21
  ['size', '' + entry.size],
22
- ['tagName', '' + entry.element ? entry.element.tagName : ''],
23
- ['className', '' + entry.element ? entry.element.className : ''],
22
+ ['tagName', '' + (entry.element?.tagName || '')],
23
+ ['className', '' + (entry.element?.className || '')],
24
24
  ['URL', '' + entry.url],
25
25
  ['Render', Math.max(entry.renderTime, entry.loadTime)]
26
26
  ],
@@ -37,11 +37,11 @@ export const lcpTimeLine = `
37
37
  track: 'LCP',
38
38
  trackGroup: 'Browsertime Timeline',
39
39
  color: 'primary-dark',
40
- tooltipText: 'LCP Candidate ' + entry.element ? entry.element.className : '',
40
+ tooltipText: 'LCP Candidate ' + (entry.element?.tagName || ''),
41
41
  properties: [
42
42
  ['size', '' + entry.size],
43
- ['tagName', '' + entry.element ? entry.element.tagName : ''],
44
- ['className', '' + entry.element ? entry.element.className : ''],
43
+ ['tagName', '' + (entry.element?.tagName || '')],
44
+ ['className', '' + (entry.element?.className || '')],
45
45
  ['URL', '' + entry.url]
46
46
  ],
47
47
  }
@@ -8,26 +8,69 @@ import { BrowserError } from '../support/errors.js';
8
8
  const delay = ms => new Promise(res => setTimeout(res, ms));
9
9
  const log = intel.getLogger('browsertime.firefox');
10
10
 
11
- // Return power usage in Wh
12
- function computePowerSum(counter) {
11
+ // Return power usage in Wh for a single counter.
12
+ function computeCounterPowerSum(counter) {
13
13
  let sum = 0;
14
14
  // Older Firefoxes see https://github.com/sitespeedio/sitespeed.io/issues/3944#issuecomment-1871090793
15
15
  if (counter.sample_groups) {
16
16
  for (const groups of counter.sample_groups) {
17
17
  const countIndex = groups.samples.schema.count;
18
- for (const sample of groups.samples.data) {
19
- sum += sample[countIndex];
18
+ // NOTE: We intentionally ignore the first index of the counters as they
19
+ // might contain incorrect values.
20
+ for (
21
+ let sampleIndex = 1;
22
+ sampleIndex < groups.samples.data.length;
23
+ sampleIndex++
24
+ ) {
25
+ sum += groups.samples.data[sampleIndex][countIndex];
20
26
  }
21
27
  }
22
28
  } else {
23
29
  const countIndex = counter.samples.schema.count;
24
- for (const sample of counter.samples.data) {
25
- sum += sample[countIndex];
30
+ // NOTE: We intentionally ignore the first index of the counters as they
31
+ // might contain incorrect values.
32
+ for (
33
+ let sampleIndex = 1;
34
+ sampleIndex < counter.samples.data.length;
35
+ sampleIndex++
36
+ ) {
37
+ sum += counter.samples.data[sampleIndex][countIndex];
26
38
  }
27
39
  }
40
+
28
41
  return sum * 1e-12;
29
42
  }
30
43
 
44
+ // Return the power usage by the whole profile including the sub processes.
45
+ // The return value is in Wh value.
46
+ function computeFullProfilePower(profile) {
47
+ let power = 0;
48
+ for (const counter of profile.counters) {
49
+ if (
50
+ counter.category === 'power' &&
51
+ // If power counters starts with "Power:", it means that there are several
52
+ // individual components that Firefox records. For Linux and Windows,
53
+ // intel CPUs might produce 'CPU package' to show the whole power
54
+ // consumption of the CPU. But on top of that it also shows some individual
55
+ // components like, DRAM, iGPU, individual CPU cores etc. We don't want
56
+ // to include them as it might produce double the power values it normally consumes.
57
+ //
58
+ // Linux track names: https://searchfox.org/mozilla-central/rev/5ad94327fc03d0e5bc6aa81c0d7d113c2dccf947/tools/profiler/core/PowerCounters-linux.cpp#48-70
59
+ // Windows track names: https://searchfox.org/mozilla-central/rev/5ad94327fc03d0e5bc6aa81c0d7d113c2dccf947/tools/profiler/core/PowerCounters-win.cpp#32-55
60
+ (!counter.name.startsWith('Power:') ||
61
+ counter.name === 'Power: CPU package')
62
+ ) {
63
+ power += computeCounterPowerSum(counter);
64
+ }
65
+ }
66
+
67
+ for (const subprocessProfile of profile.processes) {
68
+ power += computeFullProfilePower(subprocessProfile);
69
+ }
70
+
71
+ return power;
72
+ }
73
+
31
74
  /**
32
75
  * Timeout a promise after ms. Use promise.race to compete
33
76
  * about the timeout and the promise.
@@ -213,20 +256,15 @@ export class GeckoProfiler {
213
256
  geckoProfilerDefaults.features
214
257
  );
215
258
  if (chosenFeatures.includes('power')) {
216
- log.info('Collecting CPU power consumtion');
259
+ log.info('Collecting CPU power consumption');
217
260
  const profile = JSON.parse(
218
261
  await storageManager.readData(
219
262
  `geckoProfile-${index}.json`,
220
263
  path.join(pathToFolder(url, options))
221
264
  )
222
265
  );
223
- let power = 0;
224
- for (const counter of profile.counters) {
225
- if (counter.category === 'power') {
226
- power += computePowerSum(counter);
227
- }
228
- }
229
- result.powerConsumption = Number(power);
266
+
267
+ result.powerConsumption = computeFullProfilePower(profile);
230
268
  } else {
231
269
  log.warning(
232
270
  'Missing power setting in geckoProfilerParams.features so power will not be collected'
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "browsertime",
3
3
  "description": "Get performance metrics from your web page using Browsertime.",
4
- "version": "23.4.0",
4
+ "version": "23.4.2",
5
5
  "bin": "./bin/browsertime.js",
6
6
  "type": "module",
7
7
  "types": "./types/scripting.d.ts",
@@ -1 +1 @@
1
- {"version":3,"file":"geckoProfiler.d.ts","sourceRoot":"","sources":["../../lib/firefox/geckoProfiler.js"],"names":[],"mappings":"AAmDA;IACE,4DAKC;IAJC,YAAoB;IACpB,oBAAoC;IACpC,mBAAoC;IACpC,aAAsB;IAGxB,sBA2FC;IAED,uDAuGC;IAED,oBAAgB;CACjB"}
1
+ {"version":3,"file":"geckoProfiler.d.ts","sourceRoot":"","sources":["../../lib/firefox/geckoProfiler.js"],"names":[],"mappings":"AA8FA;IACE,4DAKC;IAJC,YAAoB;IACpB,oBAAoC;IACpC,mBAAoC;IACpC,aAAsB;IAGxB,sBA2FC;IAED,uDAkGC;IAED,oBAAgB;CACjB"}