|
19 | 19 | /**
|
20 | 20 | * External dependencies
|
21 | 21 | */
|
22 |
| -import puppeteer from 'puppeteer'; |
| 22 | +import puppeteer, { Browser } from 'puppeteer'; |
23 | 23 | import round from 'lodash-es/round.js';
|
24 | 24 |
|
25 | 25 | /**
|
@@ -63,45 +63,101 @@ export const options = [
|
63 | 63 | description:
|
64 | 64 | 'Whether to show more granular percentiles instead of only the median',
|
65 | 65 | },
|
| 66 | + { |
| 67 | + argname: '-t, --throttle-cpu <factor>', |
| 68 | + description: 'Enable CPU throttling to emulate slow CPUs', |
| 69 | + }, |
66 | 70 | ];
|
67 | 71 |
|
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.` |
74 | 105 | );
|
75 |
| - return; |
76 | 106 | }
|
77 | 107 |
|
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 ); |
79 | 134 | const results = [];
|
80 | 135 |
|
81 | 136 | const browser = await puppeteer.launch();
|
82 | 137 |
|
83 | 138 | 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 | + ); |
88 | 143 |
|
89 | 144 | results.push( [ url, completeRequests, metrics ] );
|
90 | 145 | }
|
91 | 146 |
|
92 | 147 | await browser.close();
|
93 | 148 |
|
94 | 149 | 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.' ) ); |
100 | 151 | } else {
|
101 | 152 | outputResults( opt, results );
|
102 | 153 | }
|
103 | 154 | }
|
104 | 155 |
|
| 156 | +/** |
| 157 | + * @param {Browser} browser |
| 158 | + * @param {Params} params |
| 159 | + * @return {Promise<{completeRequests: number, metrics: {}}>} Results |
| 160 | + */ |
105 | 161 | async function benchmarkURL( browser, params ) {
|
106 | 162 | /*
|
107 | 163 | * For now this only includes load time metrics.
|
@@ -154,6 +210,9 @@ async function benchmarkURL( browser, params ) {
|
154 | 210 |
|
155 | 211 | for ( requestNum = 0; requestNum < params.amount; requestNum++ ) {
|
156 | 212 | const page = await browser.newPage();
|
| 213 | + if ( params.cpuThrottleFactor ) { |
| 214 | + await page.emulateCPUThrottling( params.cpuThrottleFactor ); |
| 215 | + } |
157 | 216 |
|
158 | 217 | // Set viewport similar to @wordpress/e2e-test-utils 'large' configuration.
|
159 | 218 | await page.setViewport( { width: 960, height: 700 } );
|
|
0 commit comments