Skip to content

Commit 7575fec

Browse files
committed
lib: put node:bench behind an --experimental-bench flag
Signed-off-by: James M Snell <jasnell@gmail.com> Assisted-by: Opencode
1 parent 7b23fc6 commit 7575fec

41 files changed

Lines changed: 243 additions & 40 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎benchmark/_node-bench.js‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ function runBenchmark(binary, file, options) {
5353
const args = [
5454
...options.nodeArgs,
5555
'--no-warnings',
56+
'--experimental-bench',
5657
'--bench',
5758
'--bench-reporter=json',
5859
'--bench-samples=1',

‎doc/api/bench.md‎

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ added: REPLACEME
1212

1313
The `node:bench` module supports defining and running JavaScript benchmarks in
1414
the current process, and running one benchmark file in a fresh child process.
15-
To access it:
15+
The module is only available when Node.js is started with the
16+
`--experimental-bench` flag and can only be imported with the `node:` scheme:
1617

1718
```mjs
1819
import { bench, suite } from 'node:bench';
@@ -22,8 +23,6 @@ import { bench, suite } from 'node:bench';
2223
const { bench, suite } = require('node:bench');
2324
```
2425

25-
This module is only available under the `node:` scheme.
26-
2726
## Example benchmark
2827

2928
Save the following as `benchmark.mjs`:
@@ -57,7 +56,7 @@ suite('URL', () => {
5756
Run the benchmark from the command line:
5857

5958
```console
60-
node --bench benchmark.mjs
59+
node --experimental-bench --bench benchmark.mjs
6160
```
6261

6362
Benchmarks are executed serially in declaration order. Declared benchmarks are
@@ -183,8 +182,8 @@ declarations and a second call to `run()` is an error.
183182
The `--bench` flag runs one or more explicit benchmark files or glob patterns:
184183

185184
```console
186-
node --bench benchmark.mjs
187-
node --bench --bench-reporter=json 'benchmarks/**/*.js'
185+
node --experimental-bench --bench benchmark.mjs
186+
node --experimental-bench --bench --bench-reporter=json 'benchmarks/**/*.js'
188187
```
189188

190189
Files are sorted and executed serially. The default

‎doc/api/cli.md‎

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -482,10 +482,13 @@ Starts the Node.js command-line benchmark runner. At least one explicit file or
482482
glob pattern is required:
483483

484484
```console
485-
node --bench benchmark.mjs
486-
node --bench 'benchmarks/**/*.js'
485+
node --experimental-bench --bench benchmark.mjs
486+
node --experimental-bench --bench 'benchmarks/**/*.js'
487487
```
488488

489+
The `--experimental-bench` flag is required to use this flag or any other
490+
`--bench-*` option.
491+
489492
Quote glob patterns to prevent expansion by the shell. Matching files are
490493
sorted and executed serially. By default, each file runs in a separate child
491494
process. Benchmark files declare benchmarks using `node:bench`; they must not
@@ -1215,6 +1218,16 @@ changes:
12151218
12161219
Enable experimental import support for `.node` addons.
12171220

1221+
### `--experimental-bench`
1222+
1223+
<!-- YAML
1224+
added: REPLACEME
1225+
-->
1226+
1227+
> Stability: 1 - Experimental
1228+
1229+
Enable the experimental `node:bench` module and command-line benchmark runner.
1230+
12181231
### `--experimental-config-file=path`, `--experimental-config-file`
12191232

12201233
<!-- YAML
@@ -4074,6 +4087,7 @@ one is included in the list below.
40744087
* `--entry-url`
40754088
* `--experimental-abortcontroller`
40764089
* `--experimental-addon-modules`
4090+
* `--experimental-bench`
40774091
* `--experimental-detect-module`
40784092
* `--experimental-dtls`
40794093
* `--experimental-eventsource`

‎doc/node-config-schema.json‎

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,63 @@
4545
"$schema": {
4646
"type": "string"
4747
},
48+
"bench": {
49+
"type": "object",
50+
"additionalProperties": false,
51+
"required": [],
52+
"properties": {
53+
"bench": {
54+
"type": "boolean",
55+
"description": "launch benchmark runner on startup"
56+
},
57+
"bench-isolation": {
58+
"type": "string",
59+
"description": "configures the type of benchmark isolation used in the benchmark runner"
60+
},
61+
"bench-name-pattern": {
62+
"type": "string",
63+
"description": "run benchmarks whose name matches this regular expression"
64+
},
65+
"bench-reporter": {
66+
"oneOf": [
67+
{
68+
"type": "string"
69+
},
70+
{
71+
"type": "array",
72+
"minItems": 1,
73+
"items": {
74+
"type": "string"
75+
}
76+
}
77+
],
78+
"description": "report benchmark output using the given reporter"
79+
},
80+
"bench-reporter-destination": {
81+
"oneOf": [
82+
{
83+
"type": "string"
84+
},
85+
{
86+
"type": "array",
87+
"minItems": 1,
88+
"items": {
89+
"type": "string"
90+
}
91+
}
92+
],
93+
"description": "report the given benchmark reporter to the given destination"
94+
},
95+
"bench-samples": {
96+
"type": "number",
97+
"description": "specify the number of measured benchmark samples"
98+
},
99+
"bench-warmup": {
100+
"type": "number",
101+
"description": "specify the number of unreported benchmark warmup samples"
102+
}
103+
}
104+
},
48105
"nodeOptions": {
49106
"additionalProperties": false,
50107
"required": [],
@@ -119,6 +176,52 @@
119176
"type": "boolean",
120177
"description": "Improve AsyncLocalStorage performance with AsyncContextFrame"
121178
},
179+
"bench-isolation": {
180+
"type": "string",
181+
"description": "configures the type of benchmark isolation used in the benchmark runner"
182+
},
183+
"bench-name-pattern": {
184+
"type": "string",
185+
"description": "run benchmarks whose name matches this regular expression"
186+
},
187+
"bench-reporter": {
188+
"oneOf": [
189+
{
190+
"type": "string"
191+
},
192+
{
193+
"type": "array",
194+
"minItems": 1,
195+
"items": {
196+
"type": "string"
197+
}
198+
}
199+
],
200+
"description": "report benchmark output using the given reporter"
201+
},
202+
"bench-reporter-destination": {
203+
"oneOf": [
204+
{
205+
"type": "string"
206+
},
207+
{
208+
"type": "array",
209+
"minItems": 1,
210+
"items": {
211+
"type": "string"
212+
}
213+
}
214+
],
215+
"description": "report the given benchmark reporter to the given destination"
216+
},
217+
"bench-samples": {
218+
"type": "number",
219+
"description": "specify the number of measured benchmark samples"
220+
},
221+
"bench-warmup": {
222+
"type": "number",
223+
"description": "specify the number of unreported benchmark warmup samples"
224+
},
122225
"conditions": {
123226
"oneOf": [
124227
{
@@ -209,6 +312,10 @@
209312
"type": "boolean",
210313
"description": "experimental import support for addons"
211314
},
315+
"experimental-bench": {
316+
"type": "boolean",
317+
"description": "experimental node:bench module and benchmark runner"
318+
},
212319
"experimental-detect-module": {
213320
"type": "boolean",
214321
"description": "when ambiguous modules fail to evaluate because they contain ES module syntax, try again to evaluate them as ES modules"

‎doc/node.1‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,9 +296,11 @@ Error: Access to this API has been restricted
296296
Starts the Node.js command-line benchmark runner. At least one explicit file or
297297
glob pattern is required:
298298
.Bd -literal
299-
node --bench benchmark.mjs
300-
node --bench 'benchmarks/**/*.js'
299+
node --experimental-bench --bench benchmark.mjs
300+
node --experimental-bench --bench 'benchmarks/**/*.js'
301301
.Ed
302+
The \fB--experimental-bench\fR flag is required to use this flag or any other
303+
\fB--bench-*\fR option.
302304
Quote glob patterns to prevent expansion by the shell. Matching files are
303305
sorted and executed serially. By default, each file runs in a separate child
304306
process. Benchmark files declare benchmarks using \fBnode:bench\fR; they must not
@@ -677,6 +679,9 @@ It is possible to run code containing inline types unless the
677679
.It Fl -experimental-addon-modules
678680
Enable experimental import support for \fB.node\fR addons.
679681
.
682+
.It Fl -experimental-bench
683+
Enable the experimental \fBnode:bench\fR module and command-line benchmark runner.
684+
.
680685
.It Fl -experimental-config-file Ns = Ns Ar path , Fl -experimental-config-file
681686
If present, Node.js will look for a configuration file at the specified path.
682687
If the path is not specified, Node.js will look for a \fBnode.config.json\fR file
@@ -2092,6 +2097,8 @@ one is included in the list below.
20922097
.It
20932098
\fB--experimental-addon-modules\fR
20942099
.It
2100+
\fB--experimental-bench\fR
2101+
.It
20952102
\fB--experimental-detect-module\fR
20962103
.It
20972104
\fB--experimental-dtls\fR

‎lib/internal/bench_runner/cli.js‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,11 @@ const kEventTypes = new SafeSet([
106106
'bench:diagnostic',
107107
'bench:summary',
108108
]);
109-
const kFilterArgs = ['--bench', '--experimental-default-config-file'];
109+
const kFilterArgs = [
110+
'--bench',
111+
'--experimental-bench',
112+
'--experimental-default-config-file',
113+
];
110114
const kFilterArgValues = [
111115
'--bench-isolation',
112116
'--bench-name-pattern',
@@ -741,7 +745,8 @@ function getInheritedChildArgs() {
741745
function getChildArgs(path, options) {
742746
const args = options.execArgv === undefined ?
743747
getInheritedChildArgs() : ArrayPrototypeSlice(options.execArgv);
744-
ArrayPrototypePush(args, '--bench', '--bench-isolation=none');
748+
ArrayPrototypePush(
749+
args, '--experimental-bench', '--bench', '--bench-isolation=none');
745750
if (options.namePatternSource.length > 0) {
746751
ArrayPrototypePush(
747752
args, `--bench-name-pattern=${options.namePatternSource}`);

‎lib/internal/bootstrap/realm.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ const schemelessBlockList = new SafeSet([
137137
]);
138138
// Modules that will only be enabled at run time.
139139
const experimentalModuleList = new SafeSet([
140+
'bench',
141+
'bench/reporters',
140142
'dtls',
141143
'ffi',
142144
'quic',

‎lib/internal/process/pre_execution.js‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ function prepareExecution(options) {
114114
setupNetworkInspection();
115115
setupNavigator();
116116
setupWarningHandler();
117+
setupBench();
117118
setupFFI();
118119
setupSQLite();
119120
setupStreamIter();
@@ -382,6 +383,16 @@ function setupNavigator() {
382383
defineReplaceableLazyAttribute(globalThis, 'internal/navigator', ['navigator'], false);
383384
}
384385

386+
function setupBench() {
387+
if (!getOptionValue('--experimental-bench')) {
388+
return;
389+
}
390+
391+
const { BuiltinModule } = require('internal/bootstrap/realm');
392+
BuiltinModule.allowRequireByUsers('bench');
393+
BuiltinModule.allowRequireByUsers('bench/reporters');
394+
}
395+
385396
function setupFFI() {
386397
if (!getOptionValue('--experimental-ffi')) {
387398
return;

‎src/node_builtins.cc‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ BuiltinLoader::BuiltinCategories BuiltinLoader::GetBuiltinCategories() const {
158158
#if !HAVE_FFI
159159
"internal/ffi-shared-buffer", "internal/ffi/fast-api",
160160
#endif // !HAVE_FFI
161+
"bench", // Experimental.
162+
"bench/reporters", // Experimental.
161163
"dtls", // Experimental.
162164
"ffi", // Experimental.
163165
"quic", // Experimental.

‎src/node_options.cc‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,11 @@ void EnvironmentOptions::CheckOptions(std::vector<std::string>* errors,
243243
errors->push_back("invalid value for --trace-require-module");
244244
}
245245

246+
if (has_bench_options && !experimental_bench) {
247+
errors->push_back(
248+
"--experimental-bench is required to use --bench or related options");
249+
}
250+
246251
if (bench_runner && test_runner) {
247252
errors->push_back("either --bench or --test can be used, not both");
248253
}
@@ -632,6 +637,10 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
632637
"experimental import support for addons",
633638
BOOL_FIELD(experimental_addon_modules),
634639
kAllowedInEnvvar);
640+
AddOption("--experimental-bench",
641+
"experimental node:bench module and benchmark runner",
642+
BOOL_FIELD(experimental_bench),
643+
kAllowedInEnvvar);
635644
AddOption("--experimental-abortcontroller", "", NoOp{}, kAllowedInEnvvar);
636645
AddOption("--experimental-eventsource",
637646
"experimental EventSource API",
@@ -985,40 +994,47 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
985994
"use the specified file for package map resolution",
986995
&EnvironmentOptions::experimental_package_map_path,
987996
kAllowedInEnvvar);
997+
AddOption("[has_bench_options]", "", BOOL_FIELD(has_bench_options));
988998
AddOption("--bench",
989999
"launch benchmark runner on startup",
9901000
BOOL_FIELD(bench_runner),
9911001
kDisallowedInEnvvar,
9921002
false,
9931003
OptionNamespaces::kBenchRunnerNamespace);
1004+
Implies("--bench", "[has_bench_options]");
9941005
AddOption("--bench-isolation",
9951006
"configures the type of benchmark isolation used in the benchmark "
9961007
"runner",
9971008
&EnvironmentOptions::bench_isolation,
9981009
kAllowedInEnvvar,
9991010
OptionNamespaces::kBenchRunnerNamespace);
1011+
Implies("--bench-isolation", "[has_bench_options]");
10001012
AddOption("--bench-name-pattern",
10011013
"run benchmarks whose name matches this regular expression",
10021014
&EnvironmentOptions::bench_name_pattern,
10031015
kAllowedInEnvvar,
10041016
OptionNamespaces::kBenchRunnerNamespace);
1017+
Implies("--bench-name-pattern", "[has_bench_options]");
10051018
AddOption("--bench-reporter",
10061019
"report benchmark output using the given reporter",
10071020
&EnvironmentOptions::bench_reporter,
10081021
kAllowedInEnvvar,
10091022
OptionNamespaces::kBenchRunnerNamespace);
1023+
Implies("--bench-reporter", "[has_bench_options]");
10101024
AddOption("--bench-reporter-destination",
10111025
"report the given benchmark reporter to the given destination",
10121026
&EnvironmentOptions::bench_reporter_destination,
10131027
kAllowedInEnvvar,
10141028
OptionNamespaces::kBenchRunnerNamespace);
1029+
Implies("--bench-reporter-destination", "[has_bench_options]");
10151030
AddOption("[has_bench_samples]", "", BOOL_FIELD(has_bench_samples));
10161031
AddOption("--bench-samples",
10171032
"specify the number of measured benchmark samples",
10181033
&EnvironmentOptions::bench_samples,
10191034
kAllowedInEnvvar,
10201035
OptionNamespaces::kBenchRunnerNamespace,
10211036
kStrictOptionParsing);
1037+
Implies("--bench-samples", "[has_bench_options]");
10221038
Implies("--bench-samples", "[has_bench_samples]");
10231039
AddOption("[has_bench_warmup]", "", BOOL_FIELD(has_bench_warmup));
10241040
AddOption("--bench-warmup",
@@ -1027,6 +1043,7 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
10271043
kAllowedInEnvvar,
10281044
OptionNamespaces::kBenchRunnerNamespace,
10291045
kStrictOptionParsing);
1046+
Implies("--bench-warmup", "[has_bench_options]");
10301047
Implies("--bench-warmup", "[has_bench_warmup]");
10311048
AddOption("--test",
10321049
"launch test runner on startup",

0 commit comments

Comments
 (0)