Skip to content

Commit 622c372

Browse files
authored
benchmark: add per-suite setup option
This allows us to set up fixtures for the benchmark suite only once, which can save quite a bit of time when running benchmarks that require tens of thousands of fixture files or more (e.g. the module benchmarks). PR-URL: #60574 Fixes: #58488 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
1 parent 7c85846 commit 622c372

File tree

3 files changed

+39
-5
lines changed

3 files changed

+39
-5
lines changed

benchmark/common.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class Benchmark {
2828
const argv = process.argv.slice(2);
2929
const parsed_args = this._parseArgs(argv, configs, options);
3030

31+
this.originalOptions = options;
3132
this.options = parsed_args.cli;
3233
this.extra_options = parsed_args.extra;
3334
this.combinationFilter = typeof options.combinationFilter === 'function' ? options.combinationFilter : allow;
@@ -207,6 +208,12 @@ class Benchmark {
207208
});
208209
}
209210

211+
if (this.originalOptions.setup) {
212+
// Only do this from the root process. _run() is only ever called from the root,
213+
// in child processes main is run directly.
214+
this.originalOptions.setup(this.queue);
215+
}
216+
210217
const recursive = (queueIndex) => {
211218
const config = this.queue[queueIndex];
212219

benchmark/module/module-require.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,15 @@ const benchmarkDirectory = tmpdir.resolve('nodejs-benchmark-module');
88
const bench = common.createBenchmark(main, {
99
type: ['.js', '.json', 'dir'],
1010
n: [1e4],
11+
}, {
12+
setup(configs) {
13+
tmpdir.refresh();
14+
const maxN = configs.reduce((max, c) => Math.max(max, c.n), 0);
15+
createEntryPoint(maxN);
16+
},
1117
});
1218

1319
function main({ type, n }) {
14-
tmpdir.refresh();
15-
createEntryPoint(n);
16-
1720
switch (type) {
1821
case '.js':
1922
measureJSFile(n);
@@ -24,8 +27,6 @@ function main({ type, n }) {
2427
case 'dir':
2528
measureDir(n);
2629
}
27-
28-
tmpdir.refresh();
2930
}
3031

3132
function measureJSFile(n) {

doc/contributing/writing-and-running-benchmarks.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,32 @@ The arguments of `createBenchmark` are:
591591
containing a combination of benchmark parameters. It should return `true`
592592
or `false` to indicate whether the combination should be included or not.
593593

594+
* `setup` {Function} A function that will be run once in the root process
595+
before the benchmark combinations are executed in child processes.
596+
It can be used to setup any global state required by the benchmark. Note
597+
that the JavaScript heap state will not be shared with the benchmark processes,
598+
so don't try to access any variables created in the `setup` function from
599+
the `main` function, for example.
600+
The argument passed into it is an array of all the combinations of
601+
configurations that will be executed.
602+
If tear down is necessary, register a listener for the `exit` event on
603+
`process` inside the `setup` function. In the example below, that's done
604+
by `tmpdir.refresh()`.
605+
606+
```js
607+
const tmpdir = require('../../test/common/tmpdir');
608+
const bench = common.createBenchmark(main, {
609+
type: ['fast', 'slow'],
610+
n: [1e4],
611+
}, {
612+
setup(configs) {
613+
tmpdir.refresh();
614+
const maxN = configs.reduce((max, c) => Math.max(max, c.n), 0);
615+
setupFixturesReusedForAllBenchmarks(maxN);
616+
},
617+
});
618+
```
619+
594620
`createBenchmark` returns a `bench` object, which is used for timing
595621
the runtime of the benchmark. Run `bench.start()` after the initialization
596622
and `bench.end(n)` when the benchmark is done. `n` is the number of operations

0 commit comments

Comments
 (0)