Skip to content

Commit 62f78c5

Browse files
kshutkinCopilot
andcommitted
chore: added mitata bench
Co-authored-by: Copilot <copilot@github.com>
1 parent 7eaed90 commit 62f78c5

4 files changed

Lines changed: 111 additions & 2 deletions

File tree

pnpm-lock.yaml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

store/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"build": "rollup -c && dts-buddy -m @slimlib/store:./src/index.ts",
3636
"test": "vitest run --coverage --config ../vitest.config.mjs",
3737
"bench": "node tests/benchmark.mjs -n 50 -f ./results.csv",
38+
"bench:mitata": "node tests/benchmark-mitata.mjs",
3839
"build-compress": "BUILD_COMPRESS=true rollup -c && dts-buddy -m @slimlib/store:./src/index.ts",
3940
"prepack": "pkgprn-internal --remove-sourcemaps --strip-comments --flatten=dist,types",
4041
"deopt": "node --trace-deopt tests/deopt-check.mjs 2>&1 | grep -i deoptimiz || echo 'No deoptimizations detected!'",
@@ -59,6 +60,7 @@
5960
"@rollup/plugin-terser": "^0.4.4",
6061
"@vue/reactivity": "^3.5.29",
6162
"alien-signals": "^3.1.2",
63+
"mitata": "^1.0.34",
6264
"rollup": "^4.59.0",
6365
"rollup-plugin-typescript2": "^0.36.0",
6466
"rxjs": "^7.8.2",

store/tests/benchmark-mitata.mjs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//@ts-nocheck
2+
3+
/**
4+
* Multi-framework Reactivity Benchmark (mitata edition)
5+
*
6+
* Duplicates the scenarios from tests/benchmark.mjs but drives them through
7+
* the `mitata` micro-benchmark harness, which prints per-group summary
8+
* reports comparing frameworks.
9+
*
10+
* Run with: node tests/benchmark-mitata.mjs
11+
*/
12+
13+
import { bench, group, run, summary } from 'mitata';
14+
15+
import { benchmarks, dynamicGraph, dynamicGraphConfigs, frameworks, setRunImpl } from './benchmark.mjs';
16+
17+
// Registry populated by driving every benchmark function once per framework
18+
// with a "collecting" runImpl. Each entry captures the closures needed to
19+
// re-run the scenario inside a mitata bench.
20+
//
21+
// Shape: Map<testName, Array<{ framework, setup, run, iterations }>>
22+
const registry = new Map();
23+
24+
setRunImpl((framework, name, setup, runFn, iterations = 1) => {
25+
if (!registry.has(name)) registry.set(name, []);
26+
registry.get(name).push({ framework, setup, run: runFn, iterations });
27+
});
28+
29+
// Populate the registry by invoking each benchmark for every framework.
30+
// Each benchmark function internally calls runBenchmark(...), which under the
31+
// swapped-in runImpl just records setup/run closures instead of executing.
32+
for (const benchmark of benchmarks) {
33+
for (const framework of frameworks) {
34+
try {
35+
await benchmark(framework);
36+
} catch (e) {
37+
console.error(`Failed to register ${benchmark.name} for ${framework.name}: ${e.message}`);
38+
}
39+
}
40+
}
41+
42+
for (const [name, ...benchArgs] of dynamicGraphConfigs) {
43+
for (const framework of frameworks) {
44+
try {
45+
await dynamicGraph(framework, name, ...benchArgs);
46+
} catch (e) {
47+
console.error(`Failed to register ${name} for ${framework.name}: ${e.message}`);
48+
}
49+
}
50+
}
51+
52+
// Register mitata benches, grouped by scenario name with a summary block so
53+
// mitata emits its relative comparison table per group.
54+
for (const [name, entries] of registry) {
55+
group(name, () => {
56+
summary(() => {
57+
for (const entry of entries) {
58+
const { framework, setup, run: runFn, iterations } = entry;
59+
bench(framework.name, function* () {
60+
let cleanup = framework.withBuild(() => setup(framework));
61+
// Warmup a few iterations to mirror original benchmark behavior.
62+
for (let i = 0; i < 3; i++) runFn();
63+
if (cleanup && typeof cleanup === 'function') cleanup();
64+
framework.cleanup();
65+
66+
cleanup = framework.withBuild(() => setup(framework));
67+
68+
yield () => {
69+
for (let i = 0; i < iterations; i++) runFn();
70+
};
71+
72+
if (cleanup && typeof cleanup === 'function') cleanup();
73+
framework.cleanup();
74+
});
75+
}
76+
});
77+
});
78+
}
79+
80+
await run();

store/tests/benchmark.mjs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
1515
import { parseArgs } from 'node:util';
16+
import { fileURLToPath } from 'node:url';
1617

1718
// ============================================================================
1819
// Framework Adapters
@@ -386,6 +387,8 @@ const frameworks = [
386387
svelteFramework,
387388
];
388389

390+
export { frameworks };
391+
389392
// ============================================================================
390393
// Helpers
391394
// ============================================================================
@@ -422,7 +425,9 @@ function pseudoRandom(seed = 0) {
422425
// Results: Map<testName, Map<frameworkName, number[]>> - stores all times across runs
423426
const results = new Map();
424427

425-
async function runBenchmark(framework, name, setup, run, iterations = 1) {
428+
// Default benchmark runner implementation — can be swapped out by other tools
429+
// (e.g. a mitata-based runner) via setRunImpl().
430+
async function defaultRunImpl(framework, name, setup, run, iterations = 1) {
426431
// Warmup
427432
let cleanup = framework.withBuild(() => setup(framework));
428433
for (let i = 0; i < 3; i++) run();
@@ -461,6 +466,16 @@ async function runBenchmark(framework, name, setup, run, iterations = 1) {
461466
testResults.get(framework.name).push(fastestTime);
462467
}
463468

469+
let runImpl = defaultRunImpl;
470+
471+
export function setRunImpl(fn) {
472+
runImpl = fn;
473+
}
474+
475+
async function runBenchmark(framework, name, setup, run, iterations = 1) {
476+
return runImpl(framework, name, setup, run, iterations);
477+
}
478+
464479
// Calculate mean of an array
465480
function mean(arr) {
466481
if (arr.length === 0) return 0;
@@ -1173,6 +1188,8 @@ const dynamicGraphConfigs = [
11731188
['6-100x15 - dyn50%', 100, 15, 0.5, 6, 1, 20],
11741189
];
11751190

1191+
export { benchmarks, dynamicGraph, dynamicGraphConfigs };
1192+
11761193
async function main() {
11771194
// Parse command line arguments
11781195
const { values: args } = parseArgs({
@@ -1454,4 +1471,6 @@ async function main() {
14541471
}
14551472
}
14561473

1457-
main().catch(console.error);
1474+
if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
1475+
main().catch(console.error);
1476+
}

0 commit comments

Comments
 (0)