ReviewOS

zig-utils/zig-js

Perf: outperform JavaScriptCore across the verified benchmark matrix

#44
Closed chris opened this 9 days ago ·
9 days ago

Goal

Reach and sustain higher zig-js throughput than the system JavaScriptCore on every workload and directly comparable execution mode in the repository benchmark matrix, without weakening semantics, checksums, GC safety, or no-GIL correctness.

Completed workstreams

  • benchmark symmetry and statistical rigor (#45)
  • arithmetic and property-access throughput (#46)
  • array allocation, growth, traversal, and GC throughput (#47)
  • recursive and function-call throughput (#48)
  • baseline native-code tier and symbolized attribution (#52; broader coverage in #132 and #133)
  • independent-context parallel throughput (#46, #47, #48, #62, #120, #131)
  • shared-realm no-GIL object-churn scaling (#49, #97)
  • controlled regression history and generated README scorecards (#50)
  • independent object-churn finalization and precise-nursery throughput (#44)

Accepted completion baseline

The July 29, 2026 matrix measures clean runtime commit 14d94ec and is published by 018517d with all 1,540 raw samples:

  • Direct warmed context: 10/10 wins and 2.32x geometric-mean throughput.
  • Eight independent steady contexts: 10/10 wins, 2.53x throughput, and 5.35x scaling versus JSC 4.96x.
  • Eight independent cold lifecycles: 10/10 wins, 2.52x throughput, and 5.67x scaling versus JSC 4.97x.
  • Shared realm: every workload remains above 1.0x scaling at every lane; eight-lane geometric scaling is 4.84x.

Independent object churn now wins every directly comparable row:

  • steady 1/2/4/8 lanes: 106.180/116.422/145.601/207.214 ms versus JSC 134.892/139.490/156.091/208.272 ms;
  • cold 1/2/4/8 lanes: 109.688/117.079/135.536/216.272 ms versus JSC 137.150/143.667/155.324/220.921 ms.

Evidence: report, raw samples, and README scorecard.

Completion contract

  • Each engine executes identical workload and invocation bytes for directly compared rows.
  • Single-context and independent-context parallel modes compare equivalent programming models.
  • zig-js shared-realm results are reported separately unless a semantically equivalent public JSC mode is available.
  • Every timed row is long enough and sampled enough to report medians plus dispersion.
  • On the documented reference host, zig-js wins every direct and independent-context row.
  • Shared-realm no-GIL scaling has no workload below 1.0x at any reported lane count (#97).
  • Accepted performance wins retain focused semantic, GC, no-GIL, full-unit, and TSan coverage.
  • The README and dated raw report were generated from a clean tracked worktree and reference the exact measured commit.
  • Controlled like-for-like history and generated README scorecard publication are complete (#50).

Performance claims are scoped to the recorded workload matrix and host; they are not universal claims about arbitrary JavaScript applications.

9 days ago

Performance program progress: #45 fairness protocol slice landed (82207c2/e70eeff/6fb3b28), and #51 delivered the first #48 call-path optimization in eda34f5. The fairer single-context matrix now reports JSC leads of 3.92x arithmetic, 4.31x properties, 11.08x arrays, and 8.15x Fibonacci. These are the remaining targets, not a completion claim; #44–#50 stay open.

9 days ago

Baseline native-tier foundation is now live under #52 through 2a88b8a: W^X/MAP_JIT code memory, ARM64 emitter and stable ABI, race-safe hotness/publication, context-owned teardown, and the first real bytecode-to-native constant-function path. Unsupported chunks cache fallback and the 88-group quick comparison matrix remains checksum-clean. This is infrastructure progress, not a replacement performance baseline; numeric/local/control lowering is next.

9 days ago

Opened #59 to track the remaining symmetric cold-lifecycle gap separately from warmed execution and shared scaling: /zig-utils/zig-js/issues/59.

The quick matrix after c1bd949 passes all modes/checksums. Warmed Fibonacci now wins isolated and shared/parallel comparisons, while cold startup remains a real 3x to 8x deficit on most quick rows. The cold timer boundary stays unchanged; #59 owns reducing actual context/global/parser/compiler/teardown cost before the full publication report.

9 days ago

Cold comparison progress: 1c720b36 tiers numeric candidates on their only cold invocation, and eb449b6d replaces the independent runner page allocator with a documented process-wide production allocator. Targeted full-work cold endpoints now beat JSC at both 1 and 8 lanes for all four workloads. Full-matrix rerun/publication remains pending after the remaining shared-scaling audit.

9 days ago

Shared property gap closed in 3c4e0e43: the synchronized property workload now measures ~30.8 ms at one lane and ~44.6 ms at eight lanes, below recent JSC independent-context wall times. The complete quick matrix already showed zig-js winning every symmetric direct/steady/cold row; after this commit the separate shared panel also beats JSC endpoint wall times for the property workload. Final clean full matrix and report publication are next.

9 days ago

Completion contract achieved on the documented reference matrix. The clean 616-sample report shows zig-js winning all 36 symmetric single/steady/cold rows; shared scaling is above 1.0x for every workload (6.32x arithmetic, 5.66x properties, 2.43x arrays, 4.98x Fibonacci). Measured source 42d0ec26; report/TSV ccee8842; README/docs 09d543c3. Broader array scaling (#47), general-call coverage (#48), no-GIL contention (#49), and automated regression workflow (#50) remain open follow-ups.

9 days ago

Reopening because the expanded 10-workload matrix published in fdb32d8 adds an honest object_churn gap. On measured commit db131e0, zig-js wins 9/10 direct rows and leads by 2.36x geometric mean, but object_churn is 0.59x JSC throughput directly, 0.25x at eight independent contexts, and only 0.28x shared-realm scaling. The original every-workload completion contract is therefore active again. Report: https://github.com/zig-utils/zig-js/blob/main/docs/.data/benchmark-comparison-2026-07-14.md

9 days ago

Latest validated comparison is published from runtime commit 84d2f9f4 plus harness calibration commit 3d790a60, with docs/raw evidence in 3cc2a58c.

Current headline:

  • zig-js wins 9/10 direct rows
  • 2.60x direct geometric-mean throughput lead
  • 2.55x lead at eight warmed independent contexts
  • 2.63x lead in the eight-lane cold lifecycle
  • mode-local eight-lane scaling: 4.76x zig-js vs 4.82x JSC (steady), 4.84x vs 4.73x (cold)
  • shared-realm geometric-mean scaling: 3.79x

Object churn remains the only direct loss (0.59x) and the principal shared scaling blocker, tracked in #97. Its published shared 8-lane median improved 33.0% in this slice.

Report: https://github.com/zig-utils/zig-js/blob/main/docs/.data/benchmark-comparison-2026-07-14.md Raw 1,540 samples: https://github.com/zig-utils/zig-js/blob/main/docs/.data/benchmark-comparison-2026-07-14.tsv Current main CI: https://github.com/zig-utils/zig-js/actions/runs/29364341824

9 days ago

Fresh full publication from clean measured commit c98a36c4, published by e4b72407:

The exact-parent A/B for #101 measured 12.2% faster shared8 and 3.4% faster direct with exact checksums. #101 is complete; object churn remains the sole direct JSC loss and shared lanes above 1x remains unmet, so the parent performance issues stay open.

9 days ago

July 15 accepted benchmark update:

zig-js now wins all 10 direct single-context rows, with a 2.70x geometric-mean throughput lead. At eight warmed independent contexts it leads 2.86x by geometric mean and scales 5.54x versus JSC's 5.21x. Cold eight-context throughput leads 2.78x and scales 5.29x versus 5.08x.

The remaining directly comparable losses are the multi-context object-churn rows (#62): at eight lanes, 277.124 versus 172.070 ms warmed and 351.305 versus 179.788 ms cold. Shared-realm geometric-mean scaling is 3.99x, but shared object churn remains below the completion contract at 0.33x (#97/#116).

The precise-checkpoint implementation (#118) passed focused proof, 767/767 normal tests, and 766 TSan tests plus one expected skip with no sanitizer report. The README, benchmark guide, dated report, and raw evidence are current. The umbrella remains open until every independent-context object-churn row wins and every shared workload clears the scaling contract.

9 days ago

#119 is complete and published:

  • runtime ab7b08fb; docs/evidence 88bd1b00;
  • exact order-balanced parent/candidate object-churn A/B: warmed eight-context -5.2% and -6.7%, cold -10.8% and -30.1%, direct -16.2% and -1.6%;
  • candidate profile: zero sampled mmap/munmap frames versus 76 matching parent entries;
  • current full report: 10/10 direct wins, 2.71x direct geometric-mean lead, 2.70x warmed-eight lead, 2.72x cold-eight lead;
  • full gates: 1,540 benchmark samples, 768/768 normal tests, 767 TSan plus one expected skip, docs 24/24 pages.

The full matrix was recorded at 27% battery while discharging and has elevated unrelated dispersion, so the same-session A/B—not cross-run absolute timing—is the accepted optimization evidence. Multi-context and shared object churn remain open; the issue body now carries the exact current endpoints.

9 days ago

The clean July 15 publication in 6c71f46f (measured source 0a74f7d1) closes the directly comparable object-churn gap:

  • 10/10 direct wins; 2.75x geometric-mean zig-js throughput;
  • 10/10 warmed eight-context wins; 2.95x throughput, 5.38x scaling vs JSC 5.14x;
  • 10/10 cold eight-context wins; 2.90x throughput, 5.27x scaling vs JSC 5.08x;
  • object churn: 80.380 vs 117.343 ms direct, 170.179 vs 187.303 ms warmed-eight, and 177.256 vs 189.788 ms cold-eight;
  • shared-realm geometric-mean scaling: 4.17x; shared object churn remains the only sub-1x maximum-lane row at 0.51x.

The canonical issue body is updated. Direct/independent completion is checked; #97 remains open for the separate shared-realm scaling contract. Report and all 1,540 raw samples are linked from the body and README.

9 days ago

Baseline-tier workstream #52 is now complete. Saved symbolized profiles in b3dec852 distinguish generated arithmetic code, guarded property/recurrence kernels, array runtime helpers, and residual dispatch: https://github.com/zig-utils/zig-js/blob/main/docs/.data/baseline-jit-profile-2026-07-16.md

Broader native property/array coverage is tracked separately in #132/#133 and is not a blocker for this matrix contract. The umbrella remains open only for #97: the latest exact A/B improves shared object-churn 2/4/8 lanes by 1.50x/1.93x/1.24x, but eight-lane scaling is still 0.65x.

9 days ago

Completion landed directly on main as Chris with no coauthor trailers:

  • b22fa64 bypasses owner-only realm routing while preserving monotonic sibling routing.
  • 325a12b collects cache-local nursery batches only at exact single-mutator checkpoints.
  • 4b48df1 makes placement-aware JIT compaction tests assert the actual relocation contract.
  • 14d94ec skips empty plain-object finalizer probes without bypassing shared routing or telemetry.
  • 018517d publishes the clean 1,540-sample matrix and generated README scorecard; it closes #44.

Validation: 1,462/1,462 full unit tests passed with zero leaks; focused registry, finalization, and precise-nursery tests passed in Debug and TSan; benchmark publication tests passed 7/7; 88 documentation files have valid links; the 48-page docs build passed. All directly comparable object-churn rows now win, completing the umbrella after #45, #46, #47, #48, #49, #50, #52, #62, #97, #120, #131, #132, and #133.

Sign in to comment on this issue.