Skip to content

gc: incremental old-gen work costs 14% on a program that never collects (asyncpipe, zero GC cycles) #7909

Description

@proggeramlug

Summary

asyncpipe runs zero GC cycles — no [gc] line is ever printed — and yet ~33% of its leaf profile is collector machinery the mutator pays anyway: write barriers, per-object layout side tables, and RuntimeHandleScope rooting.

PERRY_GC_MOVING_LOOP_POLLS=0 measures −14.1% on asyncpipe while still running zero GC cycles. So the cost is not collection — it is an incremental old-gen mark/sweep being driven at back-edge polls that never completes a cycle and never reports one.

This is the largest single lever found in the asyncpipe round and it was deliberately left open: turning polls off is not a shippable fix (polls are default-ON since #7721 and removing them has its own history — see #7690, and the note in CLAUDE.md that a poll in a call-free clone deletes the element-shape clone). The question is why a program that never collects pays 14% for incremental collection.

Why this matters beyond one benchmark

It falsifies a premise this campaign has been using: "zero GC cycles" was treated as "GC levers are irrelevant here." That is wrong. A pure-mutator program still pays incremental-collector machinery, and on asyncpipe that is the top item.

PERRY_WRITE_BARRIERS=0 is +0.9% here, so codegen write barriers are genuinely not the cost — the incremental drive is.

Suggested direction

  • Establish why incremental old-gen work is being scheduled at all on a heap that never triggers a collection. If the answer is "the poll unconditionally does a slice of work", the fix is a cheap due-check before the slice, not disabling polls.
  • Any fix must assert its subject was live (per CLAUDE.md's four-ways-a-gate-cannot-fail): a gate here must show incremental slices actually ran on the baseline, or it proves nothing.

Evidence

gc-handoff/ASYNC2-NOTES.md — decomposition, counters, and reproduce commands. Measured with instructions retired (dev box was at load 12–165; see gc-handoff/MEASUREMENT-PROTOCOL.md).

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