ReviewOS

zig-utils/zig-js

GC: reject impossible conservative roots before slab locks

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

Parent: #473

Measured problem

The production representative_json invocation at current main takes 2,216,853 conservative-interior ownership bucket locks out of 4,615,990 total slab-lock acquisitions. Most scanned machine words are ordinary non-heap values, but classifyConservativeInterior currently probes every size class before it can reject them.

Candidate

Maintain a monotonic, ever-issued slab-address envelope in GcCellBacking. A coherent lock-free read can reject an address outside that envelope before any bucket lock. The envelope intentionally never shrinks when tail chunks are trimmed: stale inclusion only falls back to the exact existing lookup, while stale exclusion would be unsafe.

A ReleaseFast prototype preserves the exact checksum, cell/allocation counts, and collection counts while moving:

  • conservative-interior locks: 2,216,853 → 11,277 (-99.5%)
  • ownership locks: 2,233,415 → 27,839 (-98.8%)
  • total slab locks: 4,615,990 → 2,410,414 (-47.8%)

A three-pair exact-parent screen is positive on the sustained rows:

  • representative_json: 0.9931x instructions, 0.9688x CPU, 0.9700x wall
  • anti-specialization variant: 0.9982x instructions, 0.9717x CPU
  • escaped strings: 0.9962x instructions, 0.9804x CPU
  • shallow stringify: 1.0001x instructions, 0.9737x CPU
  • reviver/depth controls remain near instruction parity; the 1-job cold controls remain checksum controls below the timing floor

Definition of done

  • Prove coherent concurrent expansion and no false-negative rejection; chunk trimming may only leave a conservative superset.
  • Pin the zero-bucket-lock rejection path and the in-range exact fallback in focused tests, including TSan.
  • Preserve JSON test262 results and required VM/tree agreement.
  • Preserve deep-input, OOM, no-GIL, and GC relocation/ownership behavior.
  • Record seven interleaved exact-parent samples with identical checksums and no hidden control regression.
  • Land as one conventional commit on main, close this issue with raw evidence, and update #473.
9 days ago

Landed and pushed to main as 3abc2fc.

Exact-source attribution

ReleaseFast binary SHA-256: 2952b7c5fd2be7ca63cc2a9c968a20d5e2a220f2a7f8d95bfdfe7ea2a8d8797b

On the exact representative_json invocation, compared with parent 934d306:

  • checksum: 324952086 → 324952086
  • GC cells: 2,010,721 → 2,010,721
  • fresh/reused/freed cells and collection counts: identical
  • conservative-interior locks: 2,216,853 → 16,863 (-99.24%)
  • all ownership locks: 2,233,415 → 33,425 (-98.50%)
  • total slab locks: 4,615,990 → 2,416,000 (-47.66%)

The earlier prototype repeat reached 11,277 conservative locks; address-layout variance changes how many ordinary words fall inside the deliberately broad envelope, but both exact runs remove more than 99% of this lock source.

Seven interleaved exact-parent pairs

Raw files: /private/tmp/zig-js-json-prod.83FAYc/pairs-1011-final-7/

rowcandidate / parent instructionsparent/candidate instruction RSDCPUwall
representative_json0.99824x0.41% / 0.48%0.99936x1.00350x
anti-specialization variant0.99327x0.68% / 0.40%0.98919x0.98813x
reviver source0.98940x0.64% / 0.61%1.00808x1.01233x
escaped strings0.99540x0.13% / 0.17%0.98601x0.98421x
stringify depth 40960.99956x0.30% / 0.33%0.99467x0.99628x
stringify shallow 40961.00034x0.29% / 0.29%1.00740x1.00977x
cold plain 4096 control1.00166x0.95% / 5.25%unscored below timing floorunscored below timing floor
cold Unicode 4096 control1.00133x0.22% / 0.42%unscored below timing floorunscored below timing floor

All checksums are exact and all Darwin thermal readings are nominal → nominal. The scored sustained rows stay within the control gate; short cold rows remain semantic/instruction controls rather than throughput claims.

Correctness and safety

  • GC cell backing: 31/31 Debug
  • coherent envelope expansion: TSan pass
  • conservative moving-nursery/native-stack integration: 5/5
  • JSON/OOM/moving-GC units: 34/34
  • shared JSON no-GIL callers under TSan: 4/4
  • test262 test/built-ins/JSON: 165 pass, 0 fail
  • required tree/VM agreement: 165 agree, 0 diverge
  • 50,000-level object and array depth probes: OK true in tree and VM
  • peak compile/link footprint: 2,142 MB or less for all final gates

The envelope is monotonic across trimming, its writer is serialized by the existing backing inner lock, and readers use a sequence-protected coherent min/max snapshot. Out-of-range values take no size-class lock; in-range values still use the existing exact chunk indexes and publication bitmaps.

Sign in to comment on this issue.