Skip to content

Roll out nursery-scoped minor to default-on + path to a best-in-class GC (tracks #6083/#6129) #6131

Description

@proggeramlug

Tracking issue so the nursery-scoped-minor rollout (from #6129, addressing #6083) doesn't get forgotten behind its off-by-default flag — and to record the path to a genuinely best-in-class GC.

State

  • perf(gc): nursery-scoped valid-pointer set for non-moving minors (#6083, opt-in) #6129 adds a nursery-scoped non-moving minor: builds the ValidPointerSet over the young generation only (+ the remembered-set old parents) instead of the whole heap. ~26% faster wall-clock on a GC-heavy workload with a large old set, identical RSS.
  • Gated behind PERRY_NURSERY_SCOPED_MINOR (default off) + a per-minor runtime gate (only when the minor is fully non-moving: no old-page defrag). The compiler is unchanged; this is a runtime env flag.
  • Off by default because a wrong old→young edge is a silent UAF (memory corruption), and the correctness surface is large (multiple remembered-set parent sources, all retention patterns, evacuation interactions). Validation caught + fixed two real bugs already (remembered-set parent validation; the fallback per-header set).

Flip-to-default-on checklist (exit criteria)

  • CI soak lane: run gc-stress + a conformance/parity shard with PERRY_NURSERY_SCOPED_MINOR=1 on every PR/push (non-gating at first). This turns "soak" into continuous automated exercise AND prevents the code from rotting.
  • Differential fuzz/stress in CI: same programs, flag on vs off → byte-identical stdout + comparable RSS, across a spread of retention/allocation patterns (Maps/Sets/WeakMap/WeakRef/FinalizationRegistry, typed arrays, proxies, closures-with-boxes, big graphs).
  • Remembered-set source audit: confirm step_dirty_old_page_walk includes exactly every parent mark_remembered_set_roots validates (currently: dirty pages, external entries, fallback headers) — add a debug assertion that panics if the mark ever validates a parent not in the young set.
  • Real-app soak: run a long-lived server workload (SSR/fastify) with the flag on for a sustained window; no corruption, expected RSS/pause.
  • Flip the default (drop the env gate to on; keep PERRY_NURSERY_SCOPED_MINOR=0 as the escape hatch).

The bigger picture: the actual best-GC path

#6083 optimizes the fallback path (conservative, non-moving, alloc-point-triggered minor). Best-in-class is different: safepoint-based, precise, MOVING (copying) minors — which Perry already implements (gc_collect_minor_copying_fast_path) but currently disables. It's disabled because GC triggers at arbitrary alloc points under conservative scan (registers unspilled), which precludes moving; and the budgeted/sliced stepper that would run precise safepoint copying minors is blocked because ~35 root scanners lack budgeted cursors.

Suggested sequence: soak+flip #6083 (this issue) → then the budgeted-stepper/copying-minor project as the primary GC push.

Metadata

Metadata

Assignees

No one assigned

    Labels

    performanceRuntime, compile-time, build-size, or memory performance

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions