lib: avoid quadratic shift() in startup snapshot callback · nodejs/node@97e32c7
1+'use strict';
2+3+// Benchmarks startup time when deserialize callbacks are registered in a
4+// startup snapshot, measuring real binary execution with --snapshot-blob.
5+6+const common = require('../common.js');
7+const { spawnSync } = require('child_process');
8+const { mkdtempSync, writeFileSync, rmSync } = require('fs');
9+const { tmpdir } = require('os');
10+const path = require('path');
11+12+const bench = common.createBenchmark(main, {
13+count: [10, 100, 1000, 10000],
14+n: [30],
15+});
16+17+function buildSnapshot(snapshotBlob, fixtureScript, count) {
18+writeFileSync(fixtureScript, `
19+'use strict';
20+const v8 = require('node:v8');
21+for (let i = 0; i < ${count}; i++) {
22+ v8.startupSnapshot.addDeserializeCallback(() => {});
23+}
24+v8.startupSnapshot.setDeserializeMainFunction(() => {});
25+`);
26+const result = spawnSync(process.execPath, [
27+'--snapshot-blob', snapshotBlob,
28+'--build-snapshot', fixtureScript,
29+]);
30+if (result.status !== 0) {
31+throw new Error(`Failed to build snapshot:\n${result.stderr}`);
32+}
33+}
34+35+function main({ n, count }) {
36+const dir = mkdtempSync(path.join(tmpdir(), 'node-bench-snapshot-'));
37+const snapshotBlob = path.join(dir, 'snapshot.blob');
38+const fixtureScript = path.join(dir, 'build.js');
39+40+try {
41+buildSnapshot(snapshotBlob, fixtureScript, count);
42+43+const warmup = 3;
44+let finished = -warmup;
45+46+while (finished < n) {
47+const child = spawnSync(process.execPath, ['--snapshot-blob', snapshotBlob]);
48+if (child.status !== 0) {
49+throw new Error(`Snapshot run failed:\n${child.stderr}`);
50+}
51+finished++;
52+if (finished === 0) bench.start();
53+if (finished === n) bench.end(n);
54+}
55+} finally {
56+rmSync(dir, { recursive: true, force: true });
57+}
58+}