Skip to content

Commit 02118bc

Browse files
fix: make benchmark workloads deterministic
1 parent 4dcd524 commit 02118bc

5 files changed

Lines changed: 107 additions & 10 deletions

File tree

benchmarks/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"private": true,
55
"type": "module",
66
"scripts": {
7+
"test": "node --test workload.test.mjs",
78
"bench:codec": "node codec.mjs",
89
"bench:sourcemap": "node sourcemap.mjs",
910
"bench:wasm": "node sourcemap-wasm.mjs",

benchmarks/real-world.mjs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { createBench, latencyMeanMs, latencyP99Ms, throughputHz } from "./codspeed.mjs";
2+
import { createDeterministicLookups, setFailureExitCode } from "./workload.mjs";
23
import { readFileSync, existsSync } from "node:fs";
34
import { dirname, join } from "node:path";
45
import { fileURLToPath } from "node:url";
@@ -13,6 +14,9 @@ import { SourceMap as NapiSourceMap } from "../packages/sourcemap/index.js";
1314

1415
const __dirname = dirname(fileURLToPath(import.meta.url));
1516
const fixturesDir = join(__dirname, "fixtures");
17+
const LOOKUP_COUNT = 1_000;
18+
const LOOKUP_MAX_COLUMN = 200;
19+
const LOOKUP_SEED = 0x5eed1234;
1620

1721
// ── Load fixtures ────────────────────────────────────────────────
1822

@@ -80,6 +84,8 @@ const normalizePath = (s) => s?.replace(/\/\.\//g, "/") ?? null;
8084

8185
console.log("\n--- Correctness Check ---\n");
8286

87+
const correctnessResults = [];
88+
8389
for (const { name, json } of maps) {
8490
const trace = new TraceMap(json);
8591
const wasm = new SourceMap(json);
@@ -130,8 +136,11 @@ for (const { name, json } of maps) {
130136
console.log(
131137
` ${name}: WASM ${wasmPass ? "PASS" : "FAIL"}, NAPI ${napiPass ? "PASS" : "FAIL"} (${checked} lookups)`,
132138
);
139+
correctnessResults.push({ wasmPass, napiPass });
133140
}
134141

142+
setFailureExitCode(correctnessResults);
143+
135144
// ── Parse benchmarks ─────────────────────────────────────────────
136145

137146
console.log("\n--- Parse ---\n");
@@ -224,15 +233,8 @@ for (const { name, json, size } of maps) {
224233
const napi = new NapiSourceMap(json);
225234
const maxLine = wasm.lineCount;
226235

227-
const lookups = [];
228-
const flatPositions = [];
229-
230-
for (let i = 0; i < 1000; i++) {
231-
const line = Math.floor(Math.random() * maxLine);
232-
const column = Math.floor(Math.random() * 200);
233-
lookups.push({ line, column });
234-
flatPositions.push(line, column);
235-
}
236+
const lookups = createDeterministicLookups(LOOKUP_COUNT, maxLine, LOOKUP_MAX_COLUMN, LOOKUP_SEED);
237+
const flatPositions = lookups.flatMap(({ line, column }) => [line, column]);
236238
const posArray = new Int32Array(flatPositions);
237239

238240
const isLargeMap = size > 1024 * 1024;

benchmarks/workload.mjs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
const FAILURE_EXIT_CODE = 1;
2+
const UINT32_RANGE = 4_294_967_296;
3+
4+
const createRandom = (seed) => {
5+
let state = seed >>> 0;
6+
7+
return () => {
8+
state = (state + 0x6d2b79f5) >>> 0;
9+
let value = state;
10+
value = Math.imul(value ^ (value >>> 15), value | 1);
11+
value ^= value + Math.imul(value ^ (value >>> 7), value | 61);
12+
return ((value ^ (value >>> 14)) >>> 0) / UINT32_RANGE;
13+
};
14+
};
15+
16+
/** Create repeatable zero-based lookup positions within exclusive bounds. */
17+
export const createDeterministicLookups = (count, maxLine, maxColumn, seed) => {
18+
const random = createRandom(seed);
19+
const lookups = [];
20+
21+
for (let index = 0; index < count; index++) {
22+
lookups.push({
23+
line: Math.floor(random() * maxLine),
24+
column: Math.floor(random() * maxColumn),
25+
});
26+
}
27+
28+
return lookups;
29+
};
30+
31+
/** Mark the benchmark process as failed when any implementation mismatches. */
32+
export const setFailureExitCode = (results) => {
33+
const failed = results.some(({ wasmPass, napiPass }) => !wasmPass || !napiPass);
34+
35+
if (failed) {
36+
process.exitCode = FAILURE_EXIT_CODE;
37+
}
38+
};

benchmarks/workload.test.mjs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import assert from "node:assert/strict";
2+
import { afterEach, test } from "node:test";
3+
4+
import { createDeterministicLookups, setFailureExitCode } from "./workload.mjs";
5+
6+
afterEach(() => {
7+
process.exitCode = undefined;
8+
});
9+
10+
test("identical seeds create identical lookups", () => {
11+
const first = createDeterministicLookups(100, 80, 200, 12345);
12+
const second = createDeterministicLookups(100, 80, 200, 12345);
13+
14+
assert.deepEqual(first, second);
15+
});
16+
17+
test("different seeds create different lookups", () => {
18+
const first = createDeterministicLookups(100, 80, 200, 12345);
19+
const second = createDeterministicLookups(100, 80, 200, 54321);
20+
21+
assert.notDeepEqual(first, second);
22+
});
23+
24+
test("lookups stay within the configured bounds", () => {
25+
const lookups = createDeterministicLookups(1_000, 80, 200, 12345);
26+
27+
assert.equal(lookups.length, 1_000);
28+
for (const { line, column } of lookups) {
29+
assert.ok(line >= 0 && line < 80);
30+
assert.ok(column >= 0 && column < 200);
31+
}
32+
});
33+
34+
test("a failed WASM correctness result sets the process exit code", () => {
35+
setFailureExitCode([
36+
{ wasmPass: true, napiPass: true },
37+
{ wasmPass: false, napiPass: true },
38+
]);
39+
40+
assert.equal(process.exitCode, 1);
41+
});
42+
43+
test("a failed NAPI correctness result sets the process exit code", () => {
44+
setFailureExitCode([
45+
{ wasmPass: true, napiPass: true },
46+
{ wasmPass: true, napiPass: false },
47+
]);
48+
49+
assert.equal(process.exitCode, 1);
50+
});
51+
52+
test("passing correctness results leave the process exit code unchanged", () => {
53+
setFailureExitCode([{ wasmPass: true, napiPass: true }]);
54+
55+
assert.equal(process.exitCode, undefined);
56+
});

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"typos": "typos",
3030
"deny": "cargo deny check",
3131
"test": "pnpm run test:rust && pnpm run test:js",
32-
"test:js": "node --test .github/scripts/check-napi-declarations.test.mjs .github/scripts/publish-crate-if-needed.test.mjs .github/scripts/workflow-policy.test.mjs packages/codec/__tests__/codec.test.mjs packages/sourcemap/__tests__/sourcemap.test.mjs packages/sourcemap-wasm/__tests__/sourcemap-wasm.test.mjs packages/sourcemap-wasm/__tests__/coverage-utils.test.mjs packages/sourcemap-wasm/__tests__/browser.test.mjs packages/generator-wasm/__tests__/generator-wasm.test.mjs packages/remapping-wasm/__tests__/remapping-wasm.test.mjs packages/trace-mapping/__tests__/trace-mapping.test.mjs packages/trace-mapping/__tests__/compat.test.mjs packages/source-map/__tests__/source-map.test.mjs packages/gen-mapping/__tests__/gen-mapping.test.mjs packages/gen-mapping/__tests__/gen-mapping.cjs.test.cjs packages/remapping/__tests__/remapping.test.mjs packages/remapping/__tests__/remapping.cjs.test.cjs packages/remapping/__tests__/compat.test.mjs",
32+
"test:js": "node --test .github/scripts/check-napi-declarations.test.mjs .github/scripts/publish-crate-if-needed.test.mjs .github/scripts/workflow-policy.test.mjs benchmarks/workload.test.mjs packages/codec/__tests__/codec.test.mjs packages/sourcemap/__tests__/sourcemap.test.mjs packages/sourcemap-wasm/__tests__/sourcemap-wasm.test.mjs packages/sourcemap-wasm/__tests__/coverage-utils.test.mjs packages/sourcemap-wasm/__tests__/browser.test.mjs packages/generator-wasm/__tests__/generator-wasm.test.mjs packages/remapping-wasm/__tests__/remapping-wasm.test.mjs packages/trace-mapping/__tests__/trace-mapping.test.mjs packages/trace-mapping/__tests__/compat.test.mjs packages/source-map/__tests__/source-map.test.mjs packages/gen-mapping/__tests__/gen-mapping.test.mjs packages/gen-mapping/__tests__/gen-mapping.cjs.test.cjs packages/remapping/__tests__/remapping.test.mjs packages/remapping/__tests__/remapping.cjs.test.cjs packages/remapping/__tests__/compat.test.mjs",
3333
"test:rust": "cargo test",
3434
"coverage": "pnpm run coverage:rust && pnpm run coverage:js",
3535
"coverage:js": "mkdir -p coverage && node --test --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=coverage/js-lcov.info --test-reporter=spec --test-reporter-destination=stdout packages/codec/__tests__/codec.test.mjs packages/sourcemap/__tests__/sourcemap.test.mjs packages/sourcemap-wasm/__tests__/sourcemap-wasm.test.mjs packages/sourcemap-wasm/__tests__/coverage-utils.test.mjs packages/generator-wasm/__tests__/generator-wasm.test.mjs packages/remapping-wasm/__tests__/remapping-wasm.test.mjs packages/trace-mapping/__tests__/trace-mapping.test.mjs packages/trace-mapping/__tests__/compat.test.mjs packages/source-map/__tests__/source-map.test.mjs packages/gen-mapping/__tests__/gen-mapping.test.mjs packages/gen-mapping/__tests__/gen-mapping.cjs.test.cjs packages/remapping/__tests__/remapping.test.mjs packages/remapping/__tests__/remapping.cjs.test.cjs packages/remapping/__tests__/compat.test.mjs",

0 commit comments

Comments
 (0)