Wall-clock timing of benchmarks/*.psh under --release, comparing the
original Cheney-style copying collector (commit cc0c523) against the
new in-place mark-and-sweep collector. Each benchmark was run once per
build with a 240s timeout; both builds passed the full test suite.
| Benchmark | Original (copying GC) | New (mark-and-sweep) | Δ |
|---|---|---|---|
| alloc_objs.psh | 42826ms | 41224ms | −3.7% |
| arr_get.psh | 10018ms | 10009ms | ~0% |
| binary_tree.psh | 15645ms | 15838ms | +1.2% |
| fft.psh | 42ms | 41ms | ~0% |
| fib.psh | 17353ms | 16717ms | −3.7% |
| for_loop.psh | 14221ms | 13523ms | −4.9% |
| gc_alloc_speed.psh | 22190ms | 22321ms | +0.6% |
| gc_many_objs.psh | 47888ms | 18459ms | −61.5% |
| host_calls.psh | 3929ms | 3841ms | −2.2% |
| linked_list.psh | 9759ms | 9893ms | +1.4% |
| matrix_vec_mult.psh | 278ms | 274ms | −1.4% |
| mlp.psh | 23893ms | 22985ms | −3.8% |
| nbody.psh | 25048ms | 25259ms | +0.8% |
| obj_get.psh | 19546ms | 19349ms | −1.0% |
| ping_pong.psh | 15564ms | 15708ms | +0.9% |
| quicksort.psh | 10642ms | 10284ms | −3.4% |
| rasterize.psh | 44983ms | 43512ms | −3.3% |
| sha256.psh | 5700ms | 5262ms | −7.7% |
The mark-and-sweep collector is essentially performance-neutral across
the suite — every benchmark lands within ±5% of the original, well
within normal run-to-run noise, except gc_many_objs.psh, which is
61% faster. That benchmark specifically stress-tests allocating and
discarding many short-lived objects, which is where the copying
collector's repeated semispace grow/shrink (and the mmap/mprotect
calls that come with it) cost more than mark-sweep's in-place
reclaim-and-reuse via the free list. No benchmark regressed
meaningfully.