You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
perf(gc): full/fallback weak processing is an unsliced O(total heap) atomic pause #7874
#6182 made copied-minor weak processing proportional to registered weak holders, but the full/fallback path was deliberately left unchanged. As a result, one live WeakRef/WeakMap/WeakSet/FinalizationRegistry holder makes every full/fallback weak-processing phase walk every live arena object.
Full GC latency scales with unrelated heap size when a program uses even one weak holder.
js_gc_step_us / mutator-assist budgeting cannot bound the pause: a step with one unit can run the full walk.
The recent full-mark-sweep pacing work reduces how often this happens, but does not bound the individual pause when it does happen.
Proposed direction
Use WEAK_HOLDERS for full/fallback processing as well. The full cycle already has ValidPointerSet / FullCycleLiveness, and full/fallback pruning already removes dead holders via prune_dead_weak_holders. Make iteration state part of AtomicFinalizeState so the holder registry is processed in budgeted slices.
Acceptance criteria
Full/fallback weak processing cost is O(registered holders), not O(all live arena objects).
Dead/stale registry entries are safely classified and pruned before dereference; full-cycle evacuation continues to rekey addresses.
WeakProcessing maintains a cursor/snapshot and honors the supplied work budget across calls.
Add a scaling regression: a fixed one-holder workload with 10x unrelated live objects must not produce ~10x weak-processing work/pause.
Add correctness coverage for WeakRef, FinalizationRegistry, WeakMap, and WeakSet on full and fallback cycles, including dead holders and moved holders.
Successor to the copied-minor-only optimization in #6182.
Re-audit note after #7892: the original whole-arena holder-discovery pause is genuinely removed, so keeping this issue closed is appropriate. Two follow-ups from the replacement design are tracked separately: #7900 for the post-remark weak-read correctness race introduced by yielding between holders, and #7903 for remaining unbounded one-unit work inside a single large FinalizationRegistry (plus final remark).
Activity
proggeramlug commentedon Aug 12, 2026
Re-audit note after #7892: the original whole-arena holder-discovery pause is genuinely removed, so keeping this issue closed is appropriate. Two follow-ups from the replacement design are tracked separately: #7900 for the post-remark weak-read correctness race introduced by yielding between holders, and #7903 for remaining unbounded one-unit work inside a single large FinalizationRegistry (plus final remark).