Benchmarks
Each benchmark in benchmarks/ is one main.ts, compiled to a native binary by ChadScript and run under Node, plus a main.rs reference built with rustc -O. Before timing anything, the runner checks that all three print identical output; a benchmark that computes something different is thrown out.
Measured 2026-09-23 on Apple M4, macOS 26.6.2 (arm64). Node v25.3.0, Homebrew clang version 22.1.8, rustc 1.94.0 (4a4ef493e 2026-03-02). Best of 5 runs, wall clock including process startup. "vs Node" is Node's time divided by ChadScript's (above 1 means ChadScript is faster).
| Benchmark | ChadScript | Node | Rust | vs Node |
|---|---|---|---|---|
binary_trees | 231 ms | 131 ms | 200 ms | 0.57x |
fib | 25 ms | 97 ms | 29 ms | 3.90x |
map_lookup | 106 ms | 58 ms | 12 ms | 0.55x |
matmul | 106 ms | 89 ms | 6 ms | 0.85x |
montecarlo | 920 ms | 1.02 s | 932 ms | 1.11x |
nbody | 125 ms | 248 ms | 19 ms | 1.98x |
sieve | 53 ms | 113 ms | 10 ms | 2.14x |
sorting | 49 ms | 76 ms | 24 ms | 1.57x |
Startup and size
Most of these programs finish in tens of milliseconds, so process startup is part of every number above. Measured separately for examples/shapes.ts on the same machine and date with hyperfine -N (40 runs, mean):
| Time | Notes | |
|---|---|---|
| native binary | 1.4 ms ± 0.2 | 128 KB at -O2 (119 KB stripped); links only the system C library |
node --import tsx examples/shapes.ts | 42.6 ms ± 1.2 | Node v25.3.0 |
node examples/shapes.ts | 45.3 ms ± 1.3 | Node's built-in type stripping |
Reading the results
Rust is the ceiling, not the target: it has unboxed f64 arrays and no garbage collector. The interesting comparison is ChadScript against Node, because both implement JavaScript semantics for the same source: that difference is what ahead-of-time compilation buys.
The benchmarks that lose to Node point at known work, not general slowness:
map_lookupandmatmul: undernoUncheckedIndexedAccesseveryarr[i]read is typedT | undefined, and hot loops pay for handling theundefinedcase. Skipping that check for reads that are provably in range is the planned fix.binary_treesmostly allocates short-lived objects. Node's garbage collector is generational, which suits that pattern; ChadScript's collector is new and not generational yet (planned).
Regenerating
bun run docs/scripts/bench-page.ts # runs scripts/bench.ts (slow), rewrites the tableThe script records the machine, OS, toolchain versions and date with the numbers. Numbers from different machines are not comparable; rerun all of them together.
Next: Roadmap.