ReviewOS

zig-utils/zig-js

Intl.PluralRules: publish complete immutable resolved state

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

Parent: #475 Related benchmark/evidence: #460

Problem

Intl.PluralRules performs its observable option reads at construction but stores the normalized record in a hidden ordinary object. select repeatedly rereads locale, type, notation, and fraction digits; resolvedOptions re-traverses the full digit/rounding record and rebuilds category selection from generic properties.

The existing representative_intl_plural_rules_select boundary keeps formatters outside the timed region and executes 102,400 warmed selections across cardinal/ordinal locales and numeric shapes. Current zig-js and system JSC agree on checksum 691593768. Exact-parent zig-js attribution for one 100-job invocation is:

  • property-lock acquisitions: 6,234,947
  • backing allocations: 2,655,989 / 445,942,486 bytes
  • current backing: 154,523,693 bytes; peak: 158,552,573 bytes
  • GC cells: 1,325,990; collections: 53

Single diagnostic samples were 705.7 ms in zig-js and 62.9 ms in system JSC; these are diagnostic only, not publication evidence.

Scope

  • Publish owned locale plus closed type/notation/compact-display/digit/rounding/trailing-zero fields into one immutable native record after the complete existing observable option-read sequence.
  • Make select, selectRange, category lookup, and resolvedOptions consume only that record and use its native slot as the receiver brand.
  • Preserve option getter/coercion/error order, resolvedOptions key presence/order/defaults, plural-category order, numeric coercion, and current selection semantics.
  • Account/finalize the record through the bounded backing allocator; cover OOM, bounded heap, moving GC, and concurrent read safety.
  • Compare exact-parent select and resolved-category benchmark rows at frozen checksums.

Acceptance

  • No hidden ordinary options bag remains on newly constructed PluralRules objects.
  • Focused PluralRules/test262, Intl402, OOM, GC movement, concurrent read, TSan, and full unit gates pass.
  • Exact-parent comparison reports checksum equality and quantified retained changes; retain only a real improvement.
  • No ICU/system-JSC runtime dependency, global mutable cache, skipped observable hook, or repro-specific shortcut.
9 days ago

Implemented and landed in 33d6e55b.

The change replaces the hidden normalized-options object with object-owned, GC-finalized immutable PluralRules state. select, selectRange, and resolvedOptions now require the native brand, and closed enum reflection uses process-lifetime static values.

Exact-parent evidence:

  • select checksum 691593768: median 759,081,709 -> 708,764,541 ns (-6.63%); property locks 6,234,947 -> 4,187,027 (-32.85%).
  • resolved-options checksum 872788430: median 1,994,719,958 -> 1,916,334,917 ns (-3.93%); property locks 17,500,387 -> 15,631,667 (-10.68%); allocated backing bytes down 524,431.
  • Both rows add eight bounded backing allocations for the owned record. Select adds 369 total backing bytes / 352 current and peak; resolved current/peak fall 2,310/2,711 bytes. GC-cell and collection counts are unchanged.

The first attribution build exposed a 512k GC-cell regression from dynamically allocating reflected enum strings. That build was rejected; static enum values remove the regression in the landed implementation.

Validation: PluralRules test262 53 -> 53; full Intl402 3,341 -> 3,341; focused normal and TSan 9/9; full unit suite 1,695 passed / 1 skipped / 0 failed / 0 leaked.

Sign in to comment on this issue.