Parent: #97 Follows: zig-utils/zig-gc#33
Evidence
Both exact owned-enumeration candidates retained one zig-js-wide write on every
managed allocation batch: GcCellBacking.parallel_cell_bytes_since_collection.fetchAdd.
The counter only decides when shared workers have issued the next cooperative-GC
tranche, while allocation already holds the matching size-class bucket lock.
The first traversal-only activation improved four lanes 30% but not eight. The second candidate also removed zig-gc's heap allocation lock/global aggregate writes per large batch; it improved 1/2/4-lane medians 4.8% / 1.5% / 8.1% but regressed eight lanes 6.0%.
Evaluated design
- replace the global allocation-byte RMW with per-size-class counters updated under the bucket lock already held by allocation;
- sum/reset every counter under all bucket locks at the cooperative safepoint;
- preserve exact reset/threshold semantics;
- leave the tranche, wait primitive, sweep/unpublication, batch size, and collector binding unchanged.
Result
The isolated exact-parent A/B regressed every median: 0.95x / 0.87x / 0.87x /
0.84x at 1/2/4/8 lanes. It lost every paired sample at four and eight lanes.
The candidate and its tests were therefore reverted. Raw results and the
decision are preserved in
docs/.data/object-churn-pressure-accounting-ab-2026-07-18.md.
Acceptance
- Normal and suppression-free TSan tests proved concurrent increments, exact sums, and reset exclusion for the evaluated candidate.
- Cooperative shared-nursery lifecycle tests remained exact and leak-free.
- The evaluated allocation hot path performed no heap-wide atomic RMW for tranche accounting.
- Exact-parent shared
object_churnA/B failed the 4/8 gate, so the candidate was reverted as required. - README benchmark scores remained unchanged.
Decision
The global atomic remains. Any successor needs a cheap non-blocking read path and exact reset semantics before repeating the same gate.