Repository: nodejs/node
Pull request: benchmark: add --runs support to run.js

This PR adds a new flag to benchmark/run.js. You can pass the `--runs` to define the amount of benchmark suite runs.

Changed files:
filename: benchmark/run.js
patch: @@ -12,6 +12,8 @@ const cli = new CLI(`usage: ./node run.js [options] [--] <category> ...
                             (can be repeated)
   --exclude  pattern        excludes scripts matching <pattern> (can be
                             repeated)
+  --runs   variable=value   set the amount of benchmark suite execution.
+                            Default: 1
   --set    variable=value   set benchmark variable (can be repeated)
   --format [simple|csv]     optional value that specifies the output format
   test                      only run a single configuration from the options
@@ -45,8 +47,7 @@ if (format === 'csv') {
   console.log('"filename", "configuration", "rate", "time"');
 }
 
-(function recursive(i) {
-  const filename = benchmarks[i];
+function runBenchmark(filename) {
   const scriptPath = path.resolve(__dirname, filename);
 
   const args = cli.test ? ['--test'] : cli.optional.set;
@@ -63,42 +64,52 @@ if (format === 'csv') {
     );
   }
 
-  if (format !== 'csv') {
-    console.log();
-    console.log(filename);
-  }
-
-  child.on('message', (data) => {
-    if (data.type !== 'report') {
-      return;
-    }
-    // Construct configuration string, " A=a, B=b, ..."
-    let conf = '';
-    for (const key of Object.keys(data.conf)) {
-      if (conf !== '')
-        conf += ' ';
-      conf += `${key}=${JSON.stringify(data.conf[key])}`;
-    }
-    if (format === 'csv') {
-      // Escape quotes (") for correct csv formatting
-      conf = conf.replace(/"/g, '""');
-      console.log(`"${data.name}", "${conf}", ${data.rate}, ${data.time}`);
-    } else {
-      let rate = data.rate.toString().split('.');
-      rate[0] = rate[0].replace(/(\d)(?=(?:\d\d\d)+(?!\d))/g, '$1,');
-      rate = (rate[1] ? rate.join('.') : rate[0]);
-      console.log(`${data.name} ${conf}: ${rate}`);
-    }
+  return new Promise((resolve, reject) => {
+    child.on('message', (data) => {
+      if (data.type !== 'report') {
+        return;
+      }
+      // Construct configuration string, " A=a, B=b, ..."
+      let conf = '';
+      for (const key of Object.keys(data.conf)) {
+        if (conf !== '')
+          conf += ' ';
+        conf += `${key}=${JSON.stringify(data.conf[key])}`;
+      }
+      if (format === 'csv') {
+        // Escape quotes (") for correct csv formatting
+        conf = conf.replace(/"/g, '""');
+        console.log(`"${data.name}", "${conf}", ${data.rate}, ${data.time}`);
+      } else {
+        let rate = data.rate.toString().split('.');
+        rate[0] = rate[0].replace(/(\d)(?=(?:\d\d\d)+(?!\d))/g, '$1,');
+        rate = (rate[1] ? rate.join('.') : rate[0]);
+        console.log(`${data.name} ${conf}: ${rate}`);
+      }
+    });
+    child.once('close', (code) => {
+      if (code) {
+        reject(code);
+      } else {
+        resolve(code);
+      }
+    });
   });
+}
 
-  child.once('close', (code) => {
-    if (code) {
-      process.exit(code);
+async function run() {
+  for (let i = 0; i < benchmarks.length; ++i) {
+    let runs = cli.optional.runs ?? 1;
+    const filename = benchmarks[i];
+    if (format !== 'csv') {
+      console.log();
+      console.log(filename);
     }
 
-    // If there are more benchmarks execute the next
-    if (i + 1 < benchmarks.length) {
-      recursive(i + 1);
+    while (runs-- > 0) {
+      await runBenchmark(filename);
     }
-  });
-})(0);
+  }
+}
+
+run();

filename: doc/contributing/writing-and-running-benchmarks.md
patch: @@ -174,6 +174,16 @@ It is possible to execute more groups by adding extra process arguments.
 node benchmark/run.js assert async_hooks
 ```
 
+It's also possible to execute the benchmark more than once using the
+`--runs` flag.
+
+```bash
+node benchmark/run.js --runs 10 assert async_hooks
+```
+
+This command will run the benchmark files in `benchmark/assert` and `benchmark/async_hooks`
+10 times each.
+
 #### Specifying CPU Cores for Benchmarks with run.js
 
 When using `run.js` to execute a group of benchmarks,