perf: suspend parked New Tab and Settings renderers

Merged
TE
7d ago
+320-20

Home creates unused WebKit warmups even when those pages use Chromium, and starts warm New Tab and Settings pages whose parking views have zero opacity. Warmup now checks the selected engine before allocating WebKit pages, using the latest claim options for both build and recycling. The spares now hide after their first paint (and the New Tab cover snapshot) and wake synchronously when adopted. Pending snapshot callbacks check ownership and generation before hiding anything.

Leo's request: "when it comes to the left scroll rail thing, i already said we want it ultra fast ultra responsive, but the same goes for EVERYTHING IN THE WEB UI" and "how could rendering be this fucking slow? ... There's just loads of bullshit in my sidebar that I'm not even looking at ... This is an M5 Pro ... get shit done."

No new timers or animation loops. A parked view owns a capture lifecycle callback: it wakes for a replacement cover after a late chat-list answer, then sleeps after that capture; adoption and drop clear it, and weak ownership checks reject stale calls. Paint/snapshot callbacks run once; a claim, reparent, replacement capture, dropped spare or pool release prevents a stale callback from hiding an active page. Existing transport pacing holds nonurgent pushes while hidden. Risk: a warm page's first reveal or cover image could regress, so native opening latency and captures were measured before landing.

Validation

  • python3 scripts/cmux-next/prepush-gate.py passed; app-size warnings only.
  • App compile passed at 6b1b108043c (cmux-ci compile-check --app, job 6b53ddf99dca).
  • Real-GUI native lifecycle tests passed at the final head with no skips: PageHostPool visibility 3/3 and NewTabSpareVisibilityTests.aParkedSpareWakesForItsReplacementCoverAndSleepsAgain (step 65824ea1a4f1). The old-code pool check fails its intended assertions at :27 and :42 (step 5c93507911af); the old-pool New Tab check fails the hidden-replacement assertion at :78 (step f02ee807f509).
  • Independent Astra review passed at exact head 6b1b108043c.
  • Every A/B arm used the same fleet Mac with a GUI session, exclusive measure class, fresh scratch HOME, and the default engine on both sides. Idle arms compare c83f3215 + perf-10x-idle.sh against that same baseline plus the 3a7653b0..6b1b1080 patch; feat-cmux-next had no published cmux-tui tree after c83f3215.

Performance

metricbeforeafterdeltaharness or run link
Idle footprint at launch1804.8 MB1033.2 MB−771.6 MB (−43%)Native A/B, same fleet Mac, perf-10x-idle.sh
Idle footprint, second window1170.0 MB1036.7 MB−133.3 MB (−11%)same A/B
CEF renderer footprint at launch857.7 MB363.3 MB−494.4 MBsame A/B; two hot renderers −488 MB
WebKit WebContent footprint119 MB / 3 processes45 MB / 2 processes−74 MB / 1 processsame A/B
New Tab visible p5010.8 ms14.8 ms+4.0 ms (+37%)n=24, debug.new_tab matched A/B
New Tab visible p9021.2 ms20.5 ms−0.7 ms (−3%)same A/B; one frame in every run; p=0.17
Settings claim-to-ready p5048.0 ms57.0 ms+9.0 ms (+19%)n=8, CMUX_PAGE_CLAIM_BENCH=8 matched A/B
Settings claim-to-ready p9065.7 ms61.6 ms−4.1 ms (−6%)same A/B; claim acknowledgement +3.6 ms

The Settings p50 increase is a flagged tradeoff: a small claim-path increase was observed; whether suspension causes it remains unsettled, while p90 improves and the much larger renderer and memory reduction applies at idle. The sample is eight claims, so this is recorded for follow-up rather than treated as a settled regression. New Tab visible p50 did not show a significant regression (p=0.17), p90 improved, and every run painted in one frame.

Changelog

Changed: Unused WebKit warmups are skipped; warm New Tab and Settings pages stop drawing while parked out of sight.

Before / after

Real-app first-frame and 1-second captures compare 3a7653b0 with 6b1b1080 in light and dark: New Tab at launch, New Tab after 60 seconds idle, and Settings after 60 seconds idle. No blank, stale, or wrong cover was observed. New Tab used its parked spare (spare:true) at 37.7 ms after launch and 41.4 ms after idle; these individual observations are separate from the A/B distribution above.

After: tour-new-tab

Capture tour-new-tab at 6b1b108043c9 (fleet build, capture mini, text checked for private data)

LightDark
lightdark

After: scene-settings

Capture scene-settings at 6b1b108043c9 (fleet build, capture mini, text checked for private data)

LightDark
lightdark

Before: tour-new-tab

Capture tour-new-tab at 3a7653b054ed (fleet build, capture mini, text checked for private data)

LightDark
lightdark

Before: scene-settings

Capture scene-settings at 3a7653b054ed (fleet build, capture mini, text checked for private data)

LightDark
lightdark

Agent session: agent session