Skip to content

codegen: #8589 root-spill default threshold (4M) too low — spills moderate-fan-out functions and slows their compile #8620

Closed

Description

@proggeramlug

Summary

DEFAULT_ROOT_SPILL_RELOCATIONS (4,000,000, codegen/helpers.rs) looks too low: on a synthetic entry function that estimates ~8M relocations, spilling made the compile slower than just letting RS4GC fan out — so the default fires on moderate cases that don't need it and pays the shadow-frame overhead for nothing.

Data (single runs, contended host — treat as rough)

Synthetic: N=2000 top-level object bindings, all live via a prev chain, each built through a call → ~2000 roots × ~2000 safepoints ≈ 4–8M estimated relocations.

config compile
no outline, spill OFF (plain RS4GC fan-out) 180s
no outline, spill ON (4M default → spills main, 8M est) 303s

The spilled build emits ~4001 js_shadow_slot_* for the frame; that IR is itself expensive to build, and here it cost more than the fan-out it avoided. RS4GC fan-out only becomes catastrophic at much higher relocation counts (the Claude Code cli.js @main: ~74M est, never finishes at -Os).

Recommendation

Raise the default so spilling fires only in the genuinely-catastrophic regime. The exact crossover is unmeasured — it's between ~8M (fan-out fine at 180s) and ~74M (fan-out never finishes) — so bracket it with a couple of synthetic points (e.g. 16M / 32M / 48M) and set the default just below where fan-out stops finishing in bounded time. Raising is backstopped by the post-RS4GC instruction-budget assertion (#8586), which fails loudly rather than hanging if the new threshold is ever too high for a given function.

Note

This is compile-time only — spilling main (run-once init) does not affect the emitted binary's runtime. Lower priority than the runtime-perf work, but a real compile-time regression on moderate-fan-out functions. Context: #8583 (the regression), #8589 (the spill), #8586 (the budget backstop).

Activity

  1. added
    performanceRuntime, compile-time, build-size, or memory performance
    on Aug 22, 2026
  2. added a commit that references this issue on Aug 22, 2026
  3. proggeramlug commented on Aug 24, 2026

    @proggeramlug
    ContributorAuthor

    The specific complaint here — the 4M default was too low and spilled moderate fan-out — is addressed by #8623 (merged): the default is now 32M, measured at the RS4GC fan-out cliff. Closing this. Note: getting the Claude Code cli.js bundle to compile surfaced that 32M sits above the #8586 post-RS4GC budget (1.57M), so a function whose estimate lands in (1.57M, 32M) doesn't spill yet overruns the budget and gets refused — a distinct calibration issue (opposite direction), now tracked in #8679 (preferred fix: make the budget trigger a spill-retry rather than a hard refusal).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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