ReviewOS

zig-utils/zig-js

JSON: elide temporary copies for unescaped strings

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

Problem

JsonParser.parseString currently appends every unescaped source byte into an arena ArrayList, converts that buffer to an owned slice, and then its caller copies the bytes again into a runtime string or property key. Ordinary JSON strings and keys without escapes therefore pay an avoidable temporary allocation, byte-at-a-time growth work, and two copies.

This is on the representative JSON parse hot path and amplifies allocator contention in shared realms.

Required outcome

  • Return a validated source slice directly when a JSON string contains no escapes, without changing ownership of the final runtime value or property key.
  • Keep exact WTF-8, lone-surrogate, control-character, escape, source-text reviver, duplicate-key, and __proto__ semantics.
  • Preserve failure atomicity: invalid controls/escapes and allocator failure must not publish partial strings or properties.
  • Add deterministic allocation/work witnesses for unescaped values and keys plus escaped/Unicode correctness coverage.
  • Run full JSON.parse test262, normal/TSan unit gates, and exact-parent representative JSON base/anti-specialization timing and RSS evidence.

Relationships

Child of #473. Contributes to #493, #460, and shared allocator pressure under #478.

9 days ago

Landed the implementation in 88b5b169 (perf(json): borrow unescaped source strings (#516)).

Unescaped JSON strings and keys now return a validated input slice to the caller, which still creates the final owned runtime string or shape key. This removes one temporary arena allocation and one full byte copy per plain string/key; escaped input keeps the canonical decoder.

Validation: fail-on-first-allocation plain-Unicode witness passes, escaped input returns exact OOM, raw controls remain invalid, focused witness passes normally and under TSan, full unit gate is 1,545 passed / 1 expected skip / 0 failed or leaked, and ReleaseFast JSON test262 is 165/165 with 0 flips.

Keeping #516 open for the required exact-parent representative JSON base/anti-specialization timing and RSS artifacts.

9 days ago

Completed and landed directly on main.

Both seven-pair exact-parent rows retained matching identities/checksums with no discards and measured 0.9787x / 0.9786x retired instructions. Wall time remains diagnostic-only (1.007x noisy base; 0.970x variant), peak RSS is mixed, and unavailable cache-miss counters intentionally support no cache claim.

Verification: focused allocation witness normal + TSan; full unit gate 1,545 passed / 1 expected skip / 0 failed or leaked; ReleaseFast JSON test262 165/165, flips 0 and regressions 0.

9 days ago

Follow-up stringify work #557 is complete. a7da43f4 bulk-appends ordinary output runs while retaining the owned/unescaped string behavior established here; 6dbe188f publishes plain, Unicode, mixed-escape, and surrogate controls with Test262 still 66/66.

Sign in to comment on this issue.