ReviewOS

zig-utils/zig-js

perf(json): batch ordinary spans while decoding escaped strings

#991
Closed glennmichael123 opened this 9 days ago ·
9 days ago

Parent: #473

Measured problem

At e07db37, JsonParser.parseString scans an unescaped prefix, then restarts at the opening content byte when it encounters an escape. Its decoding loop appends each ordinary byte separately.

The current-code Debug runner reproduced this on the Apple M2 Pro with Zig 0.17.0-dev.1770+5d7cf3f and the CI-pinned real zig-gc. Parsing a JSON string with two 65,536-byte ordinary spans separated by one newline escape 256 times returns checksum 33593088. A same-length plain-string control returns the same checksum. Initial diagnostic instruction counts are 12,415,348,795 escaped vs 5,933,011,039 plain. These are single-run diagnostics, not a throughput claim.

A separate 2,048-iteration run was sampled: the ordinary-byte append site accounts for 670 of 1,737 main-thread samples in its dominant call stack. The sample also exposes per-byte ArrayList capacity bookkeeping. The run completed with checksum 268744704 under the unchanged 3 GB process-tree guard.

Intended change and completion gate

  • Reuse the validated prefix; append maximal ordinary spans between escapes.
  • Preserve raw-control rejection, every escape, WTF-8/lone surrogates, property keys, reviver source text, and allocation-failure propagation.
  • Pin direct parser/OOM tests plus the Node-confirmed 85-check JS fixture.
  • Compare affected JSON test262 outcomes and required-VM/tree witnesses using the preserved exact baseline and the candidate.
  • Save before/after samples and controls with explicit build-mode/scope limits; do not claim a general production or JSC throughput win from Debug diagnostics.

The implementation will be committed and pushed independently; evidence and the close receipt will link the resulting commit and checked-in report.

9 days ago

Implementation and regressions are pushed to main in d74ac11. The parser reuses its validated prefix and copies ordinary spans between escapes. JSON test262 stays 165 pass / 0 fail; baseline and candidate each show 165 tree/VM agreements, zero divergences. The 85-check runtime fixture passes both tiers on both binaries, and the direct-root parser suite includes every-allocation failure injection. Paired workloads are checked in under bench/json_parse_{escaped,plain}.js. Collecting the seven-pair clean-commit Debug diagnostic report next; this issue stays open until that evidence is linked. Parent: #473.

9 days ago

Completed in d74ac11; evidence pushed in 200b87f. Seven alternating exact-parent pairs show 51.7% fewer retired instructions for the long escaped-string probe, with the plain control at -0.08%. Report and all raw samples: https://github.com/zig-utils/zig-js/blob/main/docs/.data/json-parse-cpu-work-2026-09-29.md and https://github.com/zig-utils/zig-js/blob/main/docs/.data/json-parse-cpu-work-2026-09-29.json . JSON stays 165 pass / 0 fail with 165 tree/VM agreements; Unicode, controls, NUL keys, reviver source and allocation-failure gates pass. Important scope clarification: these are Debug/default-arena process diagnostics, with runtime GC off. The real zig-gc revision identifies the linked dependency only. No production/JSC throughput claim. Parent #473 remains open; sibling #992 has its own measured fix.

Sign in to comment on this issue.