ReviewOS

zig-utils/zig-gc

Perf: queue allocation-metadata lock handoffs

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

Downstream zig-js #97 still spends the dominant shared-realm object-churn worker time waiting for Heap.alloc_lock while batches publish or the collector sweeps. The current TTAS + bounded-yield policy fixed repeated failing CAS writes (#26), but a fresh 10-second eight-lane profile at zig-js daf74724 / zig-gc 092d8d7 still recorded 14,619 scheduler-yield top stacks and 1,908 allocObjectBatch top stacks. Every waiter polls the shared lock word and periodically yields; short publication sections and the longer sweep tail share the same handoff path.

Scope

  • Prototype a fair queued allocation-metadata lock whose waiters spin on private/local state and hand ownership directly to the next waiter.
  • Preserve the uncontended fast path, the single-mutator lock-free path, all-list/counter/born-cell ordering, and collector exclusion.
  • Avoid heap allocation, TLS lifetime hazards, reentrancy, or abandoned stack-node references in the lock implementation.
  • Reject the design if it regresses one/two lanes or fails to materially improve both four and eight lanes in an order-balanced exact-parent downstream A/B.

Acceptance

  • Prove mutual exclusion and exact lock acquisition accounting in zig-gc tests.
  • Pass the full zig-gc heap suite and focused downstream allocation/GC/no-GIL tests, including TSan.
  • Improve downstream shared object churn at four and eight lanes with exact checksums and no one/two-lane regression.
  • Publish only the winning general implementation; document and fully revert a losing prototype.
9 days ago

Prototype completed, measured, and fully reverted; closing as a documented negative result.

Implementation screen:

  • MCS-style TLS queue node per mutator;
  • one atomic tail exchange on acquisition;
  • each waiter spun/yielded on its private node;
  • direct release or release-published ownership handoff to the successor;
  • no heap allocation and the single-mutator lock-free path remained unchanged.

The full zig-gc heap suite passed. Downstream exact checksums all matched, but the seven-sample zig-js shared object_churn screen regressed from the shipping 130.752 / 266.487 / 548.519 / 1,321.864 ms baseline to 133.367 / 282.854 / 699.749 ms at 1/2/4 lanes, and an isolated eight-lane sample took 8,885.143 ms.

Strict FIFO creates a collector/publication convoy: the cooperative collector and each new allocation batch must drain through already queued batch publishers. The current opportunistic TTAS handoff is materially better. No code is retained; acceptance intentionally requires rejecting a losing implementation.

Sign in to comment on this issue.