ReviewOS

zig-utils/zig-js

Strings: defer uninterned content hashing until first equality

#601
Closed chris opened this 8 days ago ·
8 days ago

Parents: #473, #479, #493

Finding

After #599 removed serial FNV, exact-current-main sampling still finds managed concatenation results paying deterministic XXH3 during every StringCell construction. The dedicated representative string workload samples contentHash/XXH3 repeatedly but records no StringCell.eql leaf: most temporary results are sliced, indexed, or discarded without ever consuming their content hash. #600 showed that fusing adjacent scans is neutral on isolated strings, so the next target is removing unconsumed hash work rather than rearranging it.

Scope

  • Keep ASCII/Latin-1 classification eager because representation and O(1) readers consume it.
  • Mark uninterned runtime cells as hash-pending in the existing 64-bit metadata word; do not grow StringCell.
  • Compute and atomically publish deterministic XXH3 on the first same-classification/same-length string equality. Concurrent readers may race to derive the same value but must publish one exact state without locks or data races.
  • Keep static literals and intern-table cells eagerly hashed because compile-time equality and shard selection consume their hashes.
  • Keep exact bytes authoritative after every hash comparison and preserve canonical WTF-8/flat-storage compatibility.

Security and correctness

  • Length/classification rejection stays O(1). A same-length comparison computes each pending hash at most once, so repeated adversarial comparisons do not repeatedly rescan either cell.
  • No hash-only equality, randomized semantic identity, mutable bytes, allocation, lock, process-global cache, or deferred work outside Context teardown.
  • Add direct race, collision, static-vs-runtime, interned-vs-runtime, GC relocation, moving-GC, OOM, and bounded-heap witnesses.

Acceptance

  • @sizeOf(StringCell) remains 32 bytes and no allocation/GC inventory grows.
  • Focused normal and TSan concurrency tests prove deterministic first-use publication and exact collision handling.
  • Exact-parent representative string and cold-lifecycle profiles show the constructor hash leaves removed without moving equivalent work elsewhere.
  • String/RegExp/JSON/Temporal test262 and the full sharded unit suite have zero flips/regressions.
8 days ago

Completed by perf(strings): defer unconsumed runtime hashes (#601).

Uninterned runtime StringCells now keep eager ASCII/Latin-1 classification but defer XXH3 until the first same-length, same-classification equality. A monotonic CAS publishes the deterministic result in the existing 64-bit state word; static/interned cells remain eager, exact bytes remain authoritative, and the cell stays 32 bytes. Length/classification mismatch, forced collision, static/runtime convergence, eight-thread publication, TSan, and two moving-GC relocations are permanent witnesses.

Exact-parent ReleaseFast evidence:

  • 101 alternating cold pairs: 11.487458 ms -> 9.412959 ms median (-18.06%), 101/101 candidate wins.
  • 21 alternating representative_strings pairs at 1,000 jobs: 1.006984416 s -> 1.000796042 s (-0.615%), 20/21 wins.
  • Five-second profile: strcell.contentHash top leaves 38 -> 0; candidate has no contentHash, XXH3, or equality-hash leaf.
  • Configuration and invocation execution, admission, allocation, heap, shape, and native-code inventories are exact; checksums match.
  • test262 String 1,223, RegExp 1,879, JSON 165, Temporal 4,603: 7,870 -> 7,870, zero flips/regressions.
  • Full units: 1,717 pass, 1 platform skip, 0 fail/leak. Focused normal/TSan string races: 13/13; moving-GC witness passes normal and TSan.

Sign in to comment on this issue.