ReviewOS

zig-utils/zig-gc

Perf: validate slab payloads without per-cell hash inserts

#4
Open chris opened this 8 days ago ·
8 days ago

Downstream: zig-utils/zig-js#62 Related: #3

Problem

The exact live-payload hash index is maintained for every cell so broad maybe-managed pointers can be rejected without dereferencing wild memory. For embedders whose GC backing allocator already owns fixed-size aligned slab ranges, that duplicates ownership metadata and makes hash insertion/probing the dominant cell-allocation cost. The hash-function-only experiment in #3 did not help.

Design

  • add an optional binding hook that validates whether an allocation-start address lies on an issued slot boundary owned by the heap's backing slabs;
  • let headerForPayload ask the hook before dereferencing the candidate header, then require the normal header magic;
  • skip per-cell hash insertion/removal only for allocations the hook positively identifies; retain the current exact index and authoritative all-list fallback for every other allocation/embedder;
  • clear header magic before returning a swept slab slot so stale pointers cannot validate;
  • preserve generic zig-gc behavior byte-for-byte when the hook is absent.

Acceptance criteria

  • Wild, stale, interior, arena-owned, and foreign-heap pointers are rejected safely.
  • Live slab-backed payloads resolve exactly without per-cell hash insertion.
  • Non-slab/delegated allocations and bindings without the hook retain the existing index behavior.
  • Parallel allocation/sweep and concurrent marking remain race-safe.
  • Full zig-gc and focused zig-js GC/no-GIL tests pass.
  • The downstream bounded-object-churn row materially improves with identical checksums.
8 days ago

Landed the structural slice in 304ef51, with downstream zig-js integration in zig-utils/zig-js@16c8a542.

Validation:

  • full zig-gc test suite passed;
  • full zig-js suite passed: 747/747, including concurrent marking, parallel allocation, slab reuse, and stale-cell coverage;
  • ReleaseFast object_churn completed 100 jobs × 7 samples with identical checksum 1030552128; median 1.468 s.

The implementation removes the per-cell payload-index insert/remove for slab-owned allocations, keeps the existing hash/all-list fallback for delegated allocations and bindings without the hooks, and writes an explicit non-live tag into recycled slots. I left the material downstream speedup criterion open: the short direct samples moved only slightly and are not strong enough to claim a meaningful win yet.

8 days ago

July 16 status audit: the owned-slot validation path remains active and is covered by the current full zig-gc/zig-js suites. The latest shared object-churn profile no longer shows per-cell payload-index insertion/removal; remaining managed-pointer classification is the tolerant barrier path plus backing publication lookup. However, later object-churn gains combine slab layout, batching, reuse, and publication changes, so they are not causal evidence for this issue alone. Keeping the final performance checkbox and issue open rather than retroactively attributing an unisolated win.

Sign in to comment on this issue.