ReviewOS

zig-utils/zig-gc

Perf: bound minor GC walks to the young-cell prefix

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

Downstream: zig-utils/zig-js#62

Problem

Heap.create prepends every allocation to the intrusive all-cells list. With the one-cycle nursery enabled, every new cell is young and every surviving young cell is tenured at the next minor or full collection. Therefore the active nursery is naturally a contiguous prefix of the list, but collectYoung currently whitens and sweeps through the entire old generation as well.

The current zig-js object_churn profile makes young-GC sweeping the largest named runtime cost after VM numeric dispatch was removed in zig-utils/zig-js#67.

Scope

  • make the young-prefix invariant explicit and testable;
  • stop minor whitening at the first old cell;
  • start binding-selected old-kind tracing at that boundary rather than rechecking the young prefix;
  • stop the minor sweep when it reaches the first old cell while preserving list links across promoted and reclaimed young cells;
  • make nursery disable/re-enable safe when young cells are pending, rather than permitting old allocations to split the prefix;
  • keep full collection, weak/ephemeron processing, finalization, accounting, parallel locking, and generic binding behavior correct.

Acceptance criteria

  • Mixed live/dead young prefixes are promoted/reclaimed with exact list and byte/cell accounting.
  • Old cells after the boundary are not visited by the minor whitening or sweep loops.
  • Disabling and re-enabling the nursery cannot create a split young region.
  • Full collections and repeated minor cycles preserve the invariant.
  • Weak, ephemeron, remembered-owner, parallel, and conservative-root tests remain clean.
  • Full zig-gc tests pass.
  • Clean pinned downstream object_churn A/B records exact checksum equality and no regression.
  • Commit references this issue and downstream evidence is added to zig-utils/zig-js#62.
9 days ago

Implemented and pushed to main in 0427c2d.

The collector now treats active young cells as a contiguous list prefix: minor whitening and sweeping stop at the first old cell, old-kind tracing starts at that boundary, and disabling the nursery tenures any pending prefix before later old allocations can split it. The full-collection, weak/ephemeron, remembered-owner, finalization, accounting, and generic-binding paths remain intact.

Validation:

  • full zig-gc suite passed;
  • focused nursery suite: 8/8;
  • poisoned old-boundary regression: 2/2;
  • downstream zig-js nursery integration: 7/7, including weak refs, ephemerons, finalization, mid-script collection, and parallel remembered edges;
  • clean pinned downstream 12-sample A/B: 642.951 ms baseline to 635.797 ms current, a 1.113% elapsed reduction (1.01125x), with exact checksum 1030552128 in every run.

This satisfies the issue scope and acceptance criteria. Downstream publication work remains tracked in zig-utils/zig-js#62.

Sign in to comment on this issue.