Skip to content

Benchmarks

Every number here comes from a result file committed in the repository (engine/ts/packages/bench/results). The current figures are from matrix-2026-10-31.json, produced by engine/ts/packages/bench/src/matrix.ts (re-run with RUNS=9 CLI_RUNS=5 node packages/bench/src/matrix.ts in engine/ts).

Machine. Intel(R) Xeon(R) Processor @ 2.10GHz, 4 logical CPUs, 16 GiB, Linux 6.18.44-fc-v185 x64, 2026-10-31. Versions. Node v22.23.4 (V8 12.4.254.21-node.57); Bun 1.4.4 (JavaScriptCore); rustc 1.97.0 (2d8144b78 2026-07-07).

Noise. A shared 4-vCPU cloud VM: other tenants share the CPUs, so individual timings vary (up to about 2x between runs on this VM). Each e2e figure is from fresh processes, original and compiled interleaved; best (min) is the most stable figure, median shows the spread. Treat differences under about 10% as noise.

Whole programs: original vs Viscosity, Node and Bun

Section titled “Whole programs: original vs Viscosity, Node and Bun”

Each program’s own timed section (performance.now()), 9 fresh processes per version per runtime, original and compiled interleaved, after one discarded run of each. Compiled with the TS engine (default options); the Rust CLI’s output is compared too.

Best of 9 (median in brackets), milliseconds of each program’s timed section; speed-up = original / Viscosity.

programlayoutNode originalNode ViscosityNode speed-upBun originalBun ViscosityBun speed-up
boidsfl=soa57.4 (68.6)43.8 (56.6)1.31× (1.21×)64.1 (75.4)34.6 (49.7)1.85× (1.52×)
heatcells=soa352.4 (407.3)85.7 (93.6)4.11× (4.35×)96.4 (102.6)94.5 (118.9)1.02× (0.86×)
ledgertx=soa167.5 (198.3)44.6 (48.7)3.75× (4.08×)117.5 (126.1)40.8 (52.4)2.88× (2.41×)
nbodybs=soa61.6 (71.3)51.3 (63.5)1.2× (1.12×)50 (62.8)51.6 (55.3)0.97× (1.13×)
particlesps=soa393 (423.3)90 (114)4.37× (3.71×)155.2 (178.9)51.7 (56.6)3× (3.16×)
geometric mean2.54× (2.46×)1.74× (1.62×)

The original and compiled programs’ checksums matched on every run, and each program printed the same checksum on Node and on Bun. The Rust CLI’s compiled code is byte-identical to the TypeScript engine’s for every program. Bun relative to Node (geometric mean of Node best / Bun best; above 1 means Bun is faster): original programs 1.71×, compiled programs 1.17×.

Method: viscosity build <file> to stdout, one fresh process per compile, 5 runs each, alternating TS and Rust. Wall time of the whole process, from Node’s child_process.

Over the 40-program corpus (sum of medians): TypeScript CLI 4764.6 ms, Rust CLI 435.8 ms, 10.9× faster. Outputs were byte-identical for every program.

In process. compile() in one Node process: 50 warm-up calls, then 200 timed calls per program. TS: the reference engine from source; Rust: @viscosity/wasm (nodejs target) on the same Node. Total of medians: TypeScript 14979.7 µs, Rust as WebAssembly 2846.8 µs, 5.26× faster.

Per-program figures are in matrix-2026-10-31.md.

Intel(R) Xeon(R) Processor @ 2.10GHz, Node v22.23.4 (V8 12.4.254.21-node.57), 2026-10-31. Median of N fresh-process runs of each program’s own timed section. Shared cloud VM.

programlayout chosenoriginal (ms)Viscosity (ms)speed-up
boidsfl=soa84711.18×
heatcells=soa3641103.3×
ledgertx=soa237465.11×
nbodybs=soa67611.09×
particlesps=soa405944.3×
layoutns per elementmemory (100,000 elements)
dataclass objects26.6616.0 MB
list columns43.31
array('d') columns72.73.3 MB

In CPython, columns save memory but cost time, so the Python plugin only transforms collections you annotate. See Python.