Skip to content

Commit ca343ca

Browse files
BridgeARcodebytere
authored andcommitted
benchmark: add test and all options and improve errors
This adds a new `test` option. Using it automatically uses a single minimal option matrix to verify the benchmark works as expected. Using the new `all` option makes sure all test suites are run. On top of that the benchmarks will from now on report properly what category might have a typo, if any. The http duration was also refactored to use a option instead of relying on a configuration setting. The fixture folder is ignored as test suite from now on. PR-URL: #31396 Fixes: #31083 Reviewed-By: Sam Roberts <[email protected]> Reviewed-By: Rich Trott <[email protected]>
1 parent 9f2c742 commit ca343ca

37 files changed

+292
-189
lines changed

benchmark/_cli.js

+16-6
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,24 @@ const path = require('path');
66
// Create an object of all benchmark scripts
77
const benchmarks = {};
88
fs.readdirSync(__dirname)
9-
.filter((name) => fs.statSync(path.resolve(__dirname, name)).isDirectory())
9+
.filter((name) => {
10+
return name !== 'fixtures' &&
11+
fs.statSync(path.resolve(__dirname, name)).isDirectory();
12+
})
1013
.forEach((category) => {
1114
benchmarks[category] = fs.readdirSync(path.resolve(__dirname, category))
1215
.filter((filename) => filename[0] !== '.' && filename[0] !== '_');
1316
});
1417

1518
function CLI(usage, settings) {
16-
if (!(this instanceof CLI)) return new CLI(usage, settings);
17-
1819
if (process.argv.length < 3) {
1920
this.abort(usage); // Abort will exit the process
2021
}
2122

2223
this.usage = usage;
2324
this.optional = {};
2425
this.items = [];
26+
this.test = false;
2527

2628
for (const argName of settings.arrayArgs) {
2729
this.optional[argName] = [];
@@ -34,7 +36,7 @@ function CLI(usage, settings) {
3436
if (arg === '--') {
3537
// Only items can follow --
3638
mode = 'item';
37-
} else if ('both' === mode && arg[0] === '-') {
39+
} else if (mode === 'both' && arg[0] === '-') {
3840
// Optional arguments declaration
3941

4042
if (arg[1] === '-') {
@@ -61,6 +63,8 @@ function CLI(usage, settings) {
6163

6264
// The next value can be either an option or an item
6365
mode = 'both';
66+
} else if (arg === 'test') {
67+
this.test = true;
6468
} else if (['both', 'item'].includes(mode)) {
6569
// item arguments
6670
this.items.push(arg);
@@ -83,9 +87,15 @@ CLI.prototype.abort = function(msg) {
8387
CLI.prototype.benchmarks = function() {
8488
const paths = [];
8589

90+
if (this.items.includes('all')) {
91+
this.items = Object.keys(benchmarks);
92+
}
93+
8694
for (const category of this.items) {
87-
if (benchmarks[category] === undefined)
88-
continue;
95+
if (benchmarks[category] === undefined) {
96+
console.error(`The "${category}" category does not exist.`);
97+
process.exit(1);
98+
}
8999
for (const scripts of benchmarks[category]) {
90100
if (this.shouldSkip(scripts)) continue;
91101

benchmark/_http-benchmarkers.js

+13-10
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,8 @@ class AutocannonBenchmarker {
4343
}
4444
if (!result || !result.requests || !result.requests.average) {
4545
return undefined;
46-
} else {
47-
return result.requests.average;
4846
}
47+
return result.requests.average;
4948
}
5049
}
5150

@@ -77,9 +76,8 @@ class WrkBenchmarker {
7776
const throughput = match && +match[1];
7877
if (!isFinite(throughput)) {
7978
return undefined;
80-
} else {
81-
return throughput;
8279
}
80+
return throughput;
8381
}
8482
}
8583

@@ -89,18 +87,20 @@ class WrkBenchmarker {
8987
*/
9088
class TestDoubleBenchmarker {
9189
constructor(type) {
92-
// `type` is the type ofbenchmarker. Possible values are 'http' and 'http2'.
90+
// `type` is the type of benchmarker. Possible values are 'http' and
91+
// 'http2'.
9392
this.name = `test-double-${type}`;
9493
this.executable = path.resolve(__dirname, '_test-double-benchmarker.js');
9594
this.present = fs.existsSync(this.executable);
9695
this.type = type;
9796
}
9897

9998
create(options) {
100-
const env = Object.assign({
99+
const env = {
101100
duration: options.duration,
102101
test_url: `http://127.0.0.1:${options.port}${options.path}`,
103-
}, process.env);
102+
...process.env
103+
};
104104

105105
const child = child_process.fork(this.executable,
106106
[this.type],
@@ -189,13 +189,14 @@ http_benchmarkers.forEach((benchmarker) => {
189189
});
190190

191191
exports.run = function(options, callback) {
192-
options = Object.assign({
192+
options = {
193193
port: exports.PORT,
194194
path: '/',
195195
connections: 100,
196196
duration: 5,
197197
benchmarker: exports.default_http_benchmarker,
198-
}, options);
198+
...options
199+
};
199200
if (!options.benchmarker) {
200201
callback(new Error('Could not locate required http benchmarker. See ' +
201202
`${requirementsURL} for further instructions.`));
@@ -212,6 +213,7 @@ exports.run = function(options, callback) {
212213
'is not installed'));
213214
return;
214215
}
216+
process.env.duration = process.env.duration || options.duration || 5;
215217

216218
const benchmarker_start = process.hrtime();
217219

@@ -220,7 +222,8 @@ exports.run = function(options, callback) {
220222
child.stderr.pipe(process.stderr);
221223

222224
let stdout = '';
223-
child.stdout.on('data', (chunk) => stdout += chunk.toString());
225+
child.stdout.setEncoding('utf8');
226+
child.stdout.on('data', (chunk) => stdout += chunk);
224227

225228
child.once('close', (code) => {
226229
const elapsed = process.hrtime(benchmarker_start);

benchmark/_test-double-benchmarker.js

+6-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ if (!['http', 'http2'].includes(myModule)) {
77

88
const http = require(myModule);
99

10-
const duration = process.env.duration || 0;
10+
const duration = +process.env.duration;
1111
const url = process.env.test_url;
1212

1313
const start = process.hrtime();
@@ -18,13 +18,15 @@ function request(res, client) {
1818
res.on('error', () => {});
1919
res.on('end', () => {
2020
throughput++;
21-
const diff = process.hrtime(start);
22-
if (duration > 0 && diff[0] < duration) {
21+
const [sec, nanosec] = process.hrtime(start);
22+
const ms = sec * 1000 + nanosec / 1e6;
23+
if (ms < duration * 1000) {
2324
run();
2425
} else {
2526
console.log(JSON.stringify({ throughput }));
2627
if (client) {
2728
client.destroy();
29+
process.exit(0);
2830
}
2931
}
3032
});
@@ -33,7 +35,7 @@ function request(res, client) {
3335
function run() {
3436
if (http.get) { // HTTP
3537
http.get(url, request);
36-
} else { // HTTP/2
38+
} else { // HTTP/2
3739
const client = http.connect(url);
3840
client.on('error', (e) => { throw e; });
3941
request(client.request(), client);

benchmark/async_hooks/http-server.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ const common = require('../common.js');
33

44
const bench = common.createBenchmark(main, {
55
asyncHooks: ['init', 'before', 'after', 'all', 'disabled', 'none'],
6-
connections: [50, 500]
6+
connections: [50, 500],
7+
duration: 5
78
});
89

9-
function main({ asyncHooks, connections }) {
10+
function main({ asyncHooks, connections, duration }) {
1011
if (asyncHooks !== 'none') {
1112
let hooks = {
1213
init() {},
@@ -33,6 +34,7 @@ function main({ asyncHooks, connections }) {
3334
bench.http({
3435
connections,
3536
path,
37+
duration
3638
}, () => {
3739
server.close();
3840
});

benchmark/buffers/buffer-base64-encode.js

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ const common = require('../common.js');
2525
const bench = common.createBenchmark(main, {
2626
len: [64 * 1024 * 1024],
2727
n: [32]
28+
}, {
29+
test: { len: 256 }
2830
});
2931

3032
function main({ n, len }) {

benchmark/buffers/buffer-swap.js

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ const bench = common.createBenchmark(main, {
77
method: ['swap16', 'swap32', 'swap64'/* , 'htons', 'htonl', 'htonll' */],
88
len: [64, 256, 768, 1024, 2056, 8192],
99
n: [1e6]
10+
}, {
11+
test: { len: 16 }
1012
});
1113

1214
// The htons and htonl methods below are used to benchmark the

0 commit comments

Comments
 (0)