ReviewOS

zig-utils/zig-gc

Perf: batch dead-cell backing reclamation during sweep

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

Downstream: zig-utils/zig-js#97 Related: zig-utils/zig-js#62, zig-utils/zig-js#101, #4

Evidence

Current exact direct and 8-lane shared object_churn profiles both retain Heap.sweepPhaseLocked / the embedder backing allocator free path as a major nursery cost after allocation publication and tail trimming were optimized. Direct sampling attributed 803 samples to sweep and 537 to the zig-js cell-backing free function; the shared coordinator attributed 474/727 young-collection samples to sweep and 147 directly to backing free. Each dead cell currently crosses std.mem.Allocator.free independently.

Design

  • buffer a small fixed number of already-finalized/unindexed/unlinked dead cell allocations during sweep;
  • expose an optional binding batch-free hook, with the existing individual allocator free loop as the generic byte-for-byte fallback;
  • flush without collector allocation or new OOM behavior;
  • let slab embedders amortize size-class locking and dispatch while preserving individual size/chunk accounting.

Acceptance criteria

  • Finalize, unindex, clear magic, unlink, and decrement counters before an allocation is eligible for reuse.
  • Preserve mixed kinds/sizes, minor/full collection, generic allocator fallback, and teardown behavior.
  • Use fixed collector scratch; introduce no sweep-time allocation or OOM path.
  • Add generic fallback and optional-hook tests.
  • Pass zig-gc units and TSan, plus downstream zig-js focused/full/no-GIL gates.
  • Exact-parent object-churn A/B keeps checksums and materially improves throughput without regressing direct mode.
9 days ago

Measured outcome against exact pre-change parents (zig-js e4b72407, zig-gc 6a12d5c):

  • 21 direct samples/binary: 199.013 ms -> 196.978 ms (+1.0%);
  • 21 shared 8x10 samples/binary: 541.085 ms -> 528.172 ms (+2.4%);
  • publication-load shared 8x100, 6 samples/binary: 9.788 s -> 9.823 s (-0.4%, neutral/regressive);
  • all checksums exact (1030552128, 825067776, and 8309369344).

The fixed sweep buffer and optional embedder hook were correct and passed zig-gc normal + TSan units, but amortizing dispatch/locks does not address the dominant per-cell ownership classification and intrusive free-node writes at sustained load. The implementation commit 5b4a5b2 was therefore reverted by ff29cd7; no downstream source change was retained. A successor should change slab free-state representation at the zig-js allocator layer rather than adding a generic zig-gc hook.

9 days ago

Closed as a measured dead end after the exact high-load A/B failed the material-improvement criterion.

Sign in to comment on this issue.