ReviewOS

zig-utils/zig-gc

Perf: batch same-size cell storage release during sweep

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

Problem

Heap.sweepPhaseLocked finalizes and unlinks dead cells one at a time, then returns each slab through Allocator.free. Allocation-heavy nursery cycles therefore repeat the allocator vtable dispatch and embedding-specific size-class/ownership bookkeeping for long runs of equal-size cells. Current zig-js object-churn sampling shows sweep/backing release among the dominant remaining direct costs.

Proposed contract

  • Add an optional binding hook for releasing a bounded batch of same-size dead cell allocations.
  • Keep the existing per-cell allocator-free path byte-for-byte as fallback for bindings without the hook.
  • Finalize, unindex, clear magic, unlink, and update heap/generation counters in the exact current order before queuing a slab for release.
  • Flush on size change, bounded capacity, and sweep completion.
  • Cover mixed-size runs, partial final batches, minor/full collection, and fallback behavior.

Acceptance

  • Collector tests and zig-js focused GC tests pass.
  • Exact checksum remains unchanged.
  • Interleaved baseline/candidate object-churn A/B shows a retained improvement; reject/revert otherwise.

Consumer: zig-utils/zig-js#97.

9 days ago

Implemented and pushed to main as 597b7d7 (perf(gc): batch swept cell releases (#20)).

The optional binding hook batches up to 64 same-size dead allocations, flushing on capacity, size change, and sweep completion. Finalization, payload unindexing, magic clearing, list unlinking, and heap/generation counter updates remain per-cell and in their previous order. Bindings without the hook retain the original allocator-free path. Mixed-size/partial-batch coverage, the full zig-gc suite, and full TSan suite pass.

9 days ago

CI run 29383942669 is green on 597b7d7; closing as completed.

Sign in to comment on this issue.