Skip to content

Commit c46b377

Browse files
authored
Merge pull request #59 from GoogleChromeLabs/add/throttle-parameter
Introduce emulation of CPU throttling to benchmark-web-vitals
2 parents 846d79d + a58609b commit c46b377

File tree

2 files changed

+78
-18
lines changed

2 files changed

+78
-18
lines changed

cli/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ Loads the provided URLs in a headless browser several times to measure median We
159159
* `--file` (`-f`): File with URLs (one URL per line) to run benchmark tests for.
160160
* `--output` (`-o`): The output format: Either "table" or "csv".
161161
* `--show-percentiles` (`-p`): Whether to show more granular percentiles instead of only the median.
162+
* `--throttle-cpu` (`-t`): Enable CPU throttling to emulate slow CPUs.
162163

163164
#### Examples
164165

cli/commands/benchmark-web-vitals.mjs

Lines changed: 77 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
/**
2020
* External dependencies
2121
*/
22-
import puppeteer from 'puppeteer';
22+
import puppeteer, { Browser } from 'puppeteer';
2323
import round from 'lodash-es/round.js';
2424

2525
/**
@@ -63,45 +63,101 @@ export const options = [
6363
description:
6464
'Whether to show more granular percentiles instead of only the median',
6565
},
66+
{
67+
argname: '-t, --throttle-cpu <factor>',
68+
description: 'Enable CPU throttling to emulate slow CPUs',
69+
},
6670
];
6771

68-
export async function handler( opt ) {
69-
if ( ! isValidTableFormat( opt.output ) ) {
70-
log(
71-
formats.error(
72-
'The output format provided via the --output (-o) argument must be either "table" or "csv".'
73-
)
72+
/**
73+
* @typedef Params
74+
* @property {string} output - See above.
75+
* @property {number} amount - See above.
76+
* @property {?string} file - See above.
77+
* @property {boolean} showPercentiles - See above.
78+
* @property {?number} cpuThrottleFactor - See above.
79+
* @property {?string} url - See above.
80+
*/
81+
82+
/**
83+
* @param {Object} opt
84+
* @param {?string} opt.url
85+
* @param {string|number} opt.number
86+
* @param {?string} opt.file
87+
* @param {string} opt.output
88+
* @param {boolean} opt.showPercentiles
89+
* @param {?string} opt.throttleCpu
90+
* @return {Params} Parameters.
91+
*/
92+
function getParamsFromOptions( opt ) {
93+
const params = {
94+
url: opt.url,
95+
amount: parseInt( opt.number, 10 ),
96+
file: opt.file,
97+
output: opt.output,
98+
showPercentiles: Boolean( opt.showPercentiles ),
99+
cpuThrottleFactor: null,
100+
};
101+
102+
if ( isNaN( params.amount ) ) {
103+
throw new Error(
104+
`Supplied number "${ opt.number }" is not an integer.`
74105
);
75-
return;
76106
}
77107

78-
const { number: amount } = opt;
108+
if ( ! isValidTableFormat( params.output ) ) {
109+
throw new Error(
110+
`Invalid output ${ opt.output }. The output format provided via the --output (-o) argument must be either "table" or "csv".`
111+
);
112+
}
113+
114+
if ( ! params.file && ! params.url ) {
115+
throw new Error(
116+
'You need to provide a URL to benchmark via the --url (-u) argument, or a file with multiple URLs via the --file (-f) argument.'
117+
);
118+
}
119+
120+
if ( opt.throttleCpu ) {
121+
params.cpuThrottleFactor = parseFloat( opt.throttleCpu );
122+
if ( isNaN( params.cpuThrottleFactor ) ) {
123+
throw new Error(
124+
`Supplied CPU throttle factor "${ opt.throttleCpu }" is not a number.`
125+
);
126+
}
127+
}
128+
129+
return params;
130+
}
131+
132+
export async function handler( opt ) {
133+
const params = getParamsFromOptions( opt );
79134
const results = [];
80135

81136
const browser = await puppeteer.launch();
82137

83138
for await ( const url of getURLs( opt ) ) {
84-
const { completeRequests, metrics } = await benchmarkURL( browser, {
85-
url,
86-
amount,
87-
} );
139+
const { completeRequests, metrics } = await benchmarkURL(
140+
browser,
141+
params
142+
);
88143

89144
results.push( [ url, completeRequests, metrics ] );
90145
}
91146

92147
await browser.close();
93148

94149
if ( results.length === 0 ) {
95-
log(
96-
formats.error(
97-
'You need to provide a URL to benchmark via the --url (-u) argument, or a file with multiple URLs via the --file (-f) argument.'
98-
)
99-
);
150+
log( formats.error( 'No results returned.' ) );
100151
} else {
101152
outputResults( opt, results );
102153
}
103154
}
104155

156+
/**
157+
* @param {Browser} browser
158+
* @param {Params} params
159+
* @return {Promise<{completeRequests: number, metrics: {}}>} Results
160+
*/
105161
async function benchmarkURL( browser, params ) {
106162
/*
107163
* For now this only includes load time metrics.
@@ -154,6 +210,9 @@ async function benchmarkURL( browser, params ) {
154210

155211
for ( requestNum = 0; requestNum < params.amount; requestNum++ ) {
156212
const page = await browser.newPage();
213+
if ( params.cpuThrottleFactor ) {
214+
await page.emulateCPUThrottling( params.cpuThrottleFactor );
215+
}
157216

158217
// Set viewport similar to @wordpress/e2e-test-utils 'large' configuration.
159218
await page.setViewport( { width: 960, height: 700 } );

0 commit comments

Comments
 (0)