-
Notifications
You must be signed in to change notification settings - Fork 425
Expand file tree
/
Copy pathbench.js
More file actions
103 lines (82 loc) · 3.13 KB
/
bench.js
File metadata and controls
103 lines (82 loc) · 3.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { benchmarkSolver, challengeCases, rustBaselineCommit, verifySolver } from "../shared.js";
const statusEl = document.getElementById("status");
const metaEl = document.getElementById("meta");
const outputEl = document.getElementById("output");
function log(line) {
outputEl.textContent += `${line}\n`;
console.log(line);
}
function fail(error) {
const message = error instanceof Error ? error.stack ?? error.message : String(error);
statusEl.textContent = "Failed.";
outputEl.textContent += `${message}\n`;
console.error(error);
}
window.addEventListener("error", (event) => {
fail(event.error ?? event.message);
});
window.addEventListener("unhandledrejection", (event) => {
fail(event.reason);
});
function readIntParam(name, fallback) {
const value = new URLSearchParams(location.search).get(name);
if (value === null) {
return fallback;
}
const parsed = Number.parseInt(value, 10);
if (!Number.isFinite(parsed) || parsed < 0) {
throw new Error(`${name} must be a non-negative integer`);
}
return parsed;
}
const iterations = readIntParam("iterations", 10);
const warmupRounds = readIntParam("warmup", 2);
metaEl.textContent = `iterations=${iterations}, warmup=${warmupRounds}, cases=${challengeCases.length}`;
try {
const cacheToken = Date.now();
const headModule = await import(`/out/head/browser/cap_wasm.js?cache=${cacheToken}`);
const rustModule = await import(`/out/rust/browser/cap_wasm.js?cache=${cacheToken}`);
const initHead = headModule.default;
const headSolvePow = headModule.solve_pow;
const initRust = rustModule.default;
const rustSolvePow = rustModule.solve_pow;
statusEl.textContent = "Loading wasm modules...";
log("Loading wasm modules...");
await Promise.all([initHead(), initRust()]);
log("Wasm modules loaded.");
statusEl.textContent = "Verifying solver outputs...";
log("Verifying solver outputs...");
await new Promise((resolve) => requestAnimationFrame(resolve));
verifySolver("HEAD (C)", headSolvePow);
verifySolver(`Rust (${rustBaselineCommit.slice(0, 7)})`, rustSolvePow);
log("Verification complete.");
statusEl.textContent = "Running benchmark...";
log("Running benchmark...");
await new Promise((resolve) => requestAnimationFrame(resolve));
const headResult = benchmarkSolver("HEAD (C)", headSolvePow, {
iterations,
warmupRounds,
});
const rustResult = benchmarkSolver(`Rust (${rustBaselineCommit.slice(0, 7)})`, rustSolvePow, {
iterations,
warmupRounds,
});
if (headResult.checksum !== rustResult.checksum) {
throw new Error(
`checksum mismatch: ${headResult.checksum.toString()} != ${rustResult.checksum.toString()}`,
);
}
log("Benchmark results");
log(
`${headResult.label.padEnd(14)} ${headResult.elapsedMs.toFixed(2)} ms total ` +
`(${headResult.perSolveMs.toFixed(4)} ms/solve)`,
);
log(
`${rustResult.label.padEnd(14)} ${rustResult.elapsedMs.toFixed(2)} ms total ` +
`(${rustResult.perSolveMs.toFixed(4)} ms/solve)`,
);
log(`Speedup: ${(rustResult.perSolveMs / headResult.perSolveMs).toFixed(2)}x faster on HEAD`);
statusEl.textContent = "Done.";
} catch (error) {
fail(error);
}