Parent: #50 Related: #47, #49, #53, #61, #97, #116, #118, #119, #120, #131
Delivered benchmark
The accepted comparison includes sustained short-lived ordinary-object allocation with a bounded live working set. Each lane:
- allocates a fixed 256-object ring;
- repeatedly reads a displaced object's initialized properties;
- replaces the indexed entry with a fresh three-property ordinary object;
- preserves a deterministic, exactly representable checksum over the displaced reads and bounded live tail;
- uses identical source/invocation bytes and equal jobs per lane in zig-js and JSC;
- avoids host-only GC APIs and engine-specific source recognition.
Harness validation covers checksum/work equality, timing floors, lane/job symmetry, sample counts, runner alternation, report/TSV consistency, and bounded live-set documentation. General allocation/GC optimizations preserved prototypes, initialized properties, indexed replacement, barriers, OOM behavior, and tracing semantics.
Final accepted result
The July 15, 2026 128-byte-slab report measured clean source commit 12aa217c2f66c0fe7fa95e38ec414ea5ec15a993 and was published in 78a3fc5c with 1,540 raw samples:
- direct: 101.799 ms zig-js vs 123.020 ms JSC (1.21x zig-js throughput)
- warmed eight-context: 168.520 vs 185.412 ms (1.10x; zig-js wins)
- cold eight-context: 181.819 vs 190.980 ms (1.05x; zig-js wins)
- shared 1/2/4/8 lanes: 146.979 / 273.948 / 604.686 / 1,671.114 ms
- shared eight-lane scaling/RSD: 0.70x / 7.24%
Ordinary Object is now 96 payload bytes and occupies the 128-byte managed slab. Its lazy storage wrapper owns cold/exotic state and external named/element metadata; a plain object with four or fewer named properties keeps values inline. The current object bucket uses 256 KiB chunks.
- report: https://github.com/zig-utils/zig-js/blob/main/docs/.data/benchmark-comparison-2026-07-15-128-byte-slab.md
- raw evidence: https://github.com/zig-utils/zig-js/blob/main/docs/.data/benchmark-comparison-2026-07-15-128-byte-slab.tsv
- exact-parent object-layout A/B: https://github.com/zig-utils/zig-js/blob/main/docs/.data/object-churn-128-byte-slab-ab-2026-07-15.md
Scope split
This issue owns the benchmark workload, fairness contract, validation, baseline, general object-allocation evidence, and publication. Those are complete. Shared-realm scaling is a separate engine-performance problem tracked with current attribution and acceptance criteria in #97; duplicating its >=1.0x target here made two issues represent the same unfinished work. #97 remains open, while this benchmark-delivery issue is complete.
Acceptance criteria
- Sustain fresh ordinary-object allocation and indexed replacement in the timed loop with a bounded live ring.
- Exercise multiple initialized properties, displaced-object reads, and deterministic exactly representable checksums.
- Extend harness validation and document timed boundaries, live-set behavior, and limitations.
- Calibrate equal job counts so every full-run engine/mode row exceeds the publication timing floor.
- Capture and link the initial symmetric baseline before optimization.
- Add allocation/GC evidence sufficient to identify the limiting general paths.
- Optimize only general engine behavior; preserve prototypes, accessors, proxies, barriers, OOM behavior, and GC tracing.
- Beat JSC in every fair direct and independent-context row.
- Move the distinct shared-realm scaling contract and evidence to #97.
- Pass focused semantic/GC/no-GIL tests, the comparison harness, and batched full-suite/TSan gates.
- Publish the report/TSV and README summary only after all gates pass.