Repository navigation
perf(tinybench): batch fast walltime invocations into rounds - #117
Conversation
Benchmarks in one process share allocator and JIT state, and rounds within one process are correlated, so a single process gives a biased view of a benchmark. Add the building blocks for integrations to run each walltime benchmark in several fresh processes (forks) and pool their rounds: - `walltimeIsolation(forks?)` picks the mode from the env: parent, fork (`CODSPEED_ISOLATED_BENCHMARK`), or one shared process when `CODSPEED_PROCESS_ISOLATION=false` - the fork count is `CODSPEED_WALLTIME_FORKS`, else the integration's `forks` option, else 3 - `runForks`/`runForksSync` re-run the benchmark command (keeping the V8 flags) once per fork and collect the samples each fork writes with `writeForkSamples`; a failing fork's exit code is passed on - `samplesToResult` builds tinybench-style statistics over the pooled samples Refs COD-3960
`withCodSpeed(bench, { forks })` sets the fork count of walltime runs, and
`CODSPEED_WALLTIME_FORKS` overrides it. The parent runs each task in its
forks and reports their pooled rounds; a fork runs only its task, hands its
samples over and prints no banner or summary. Simulation runs are unchanged.
Refs COD-3960
With Vitest 5, each walltime benchmark runs in fresh `vitest bench`
processes restricted to its file. The fork count resolves as
`CODSPEED_WALLTIME_FORKS`, the benchmark's or run's `forks` option,
`codspeedPlugin({ forks })`, then 3. The test timeout is scaled by the
env or plugin fork count, since every fork of a test runs within it.
Vitest's own report shows zeroed statistics for forked benchmarks; the
CodSpeed results hold the pooled rounds. Vitest 3/4 don't fork.
Closes COD-3960
Replace JSON sample transport with gzip-compressed V8 serialization to avoid constructing strings beyond the V8 string-size limit. Update both the child writer and parent reader, using fast gzip compression while preserving all samples.
Calibrate approximately 1 ms rounds from warmup and share the iteration count across isolated forks. Normalize latency statistics per invocation while retaining raw total time. Keep per-invocation hooks and concurrent tasks unbatched, and cover shared, forked, synchronous, and asynchronous execution.
Merging this PR will regress 12 benchmarks5 warnings, 1 note
Warning Please fix the performance issues or acknowledge them on CodSpeed. Performance Changes
Tip Investigate this regression by commenting Comparing Footnotes
|
TLDR: Batch fast Tinybench walltime calls into approximately 1 ms rounds to reduce timer and sample-processing overhead (stacked on #101).
Local iterative Fibonacci(10), Node 24.22.1 / Tinybench 4.0.1, 1 s measurement + 100 ms warmup per process, one run per configuration:
Peak RSS of a measuring child in the two-fork run: 3,769 MiB → 71 MiB. Local smoke checks also cover Tinybench 6.2.2, lifecycle hooks, slow rounds, concurrency, fallback, and simulation.
Closes COD-4104.