Skip to content

Let hidden windows throttle: drop backgroundThrottling: false - #73

Open
cguldogan wants to merge 1 commit into
NVIDIA:developfrom
cguldogan:pr/background-throttling
Open

cguldogan wants to merge 1 commit into
NVIDIA:developfrom
cguldogan:pr/background-throttling

Conversation

@cguldogan

Copy link
Copy Markdown

Description

Both the Overview window and the tray window are created with backgroundThrottling: false in the shared webPreferences (desktop/src/electron/window.ts). With it off, a hidden or occluded window keeps animating at full frame rate, so the app burns CPU/GPU around the clock even when nobody is looking at it.

Measured on the 0.1.1 macOS build (Apple M1 Pro) with one job running and the window hidden or on another Space: the GPU helper process sat at 52–80 % of a core and the Overview renderer at 20–25 %, unchanged by hiding the app. The never-shown tray window held its own vsync callback and burned ~5 % permanently. macOS lists PAIR as a significant energy user as a result.

This PR removes the flag so Chromium's default throttling applies. Default throttling only slows renderer timers and pauses requestAnimationFrame and CSS animations while the window is not visible. Nothing durable lives in the renderer: logs, the job history and routing are in the main process and the Go services, IPC pushes still reach a throttled renderer, and the one rAF-batched store (workloads.store) flushes on the first frame after the window is shown.

Scope

  • desktop/src/electron/window.ts: remove backgroundThrottling: false (and the stale commented-out copy of it) from the shared webPreferences, with a comment recording why.
  • Nothing else. The remaining cost while the window is visible (the always-on running-job animations: SMIL beads under a Gaussian-blur filter, always-mounted rotating rings) is a separate change.

Validation

Dev build (npm start) from this branch on macOS 26, one inference job running through the proxy, sampled with top -l 4 -s 3:

State Before (0.1.1 build) After
Window hidden / on another Space GPU helper 55–80 %, renderer 20–25 % GPU helper 0 %, renderer ~3 %
Window on screen GPU helper 26 %, renderer 25 % (unchanged by this PR)
No jobs, on screen GPU helper ~2 %

Tray popover behaviour, which is the one place throttling could show:

  • opened during a running job: shows the running job and the active node ring immediately;
  • opened after the job ended: shows Jobs (0). Updates delivered while the popover was hidden were applied on the first frame after it opened.

npm run typecheck passes.

Risk

  • Renderer-side timers (Settings service-status poll, invite-status poll during pairing, pending-action expiry sweep) run at ~1 Hz while the window is hidden and resume immediately on show. None of them gate data; they only refresh UI state.
  • No packaging, storage or protocol changes.

Checklist

  • I have read the Contributing Guidelines.
  • Every commit is signed off (git commit -s), certifying the Developer Certificate of Origin.
  • New or existing tests cover the change. (Window creation options are not covered by tests; validated manually as above.)
  • Relevant documentation is updated. (None affected; the rationale is in a code comment.)
  • I checked the diff, changed filenames, and commit messages for credentials, private data, internal URLs, internal issue identifiers, and generated artifacts.
  • I recorded the validation commands and results above.
  • I bumped any affected component in services/versions.json, and described user-visible changes above so they reach the release notes. (Desktop-only change; no service component affected.)

🤖 Generated with Claude Code

Both the Overview and the tray window were created with
backgroundThrottling: false, so a hidden or occluded window kept animating
at full frame rate. Measured on the installed 0.1.1 build: the GPU helper
sat at 50-80% of a core and the never-shown tray renderer at ~5% around
the clock, unchanged by hiding the app or moving it to another Space.

Chromium's default throttling only slows renderer timers and pauses rAF and
CSS animations while the window is not visible. Nothing durable lives in
the renderer: logs, job history and routing are in the main process and
the Go services, IPC pushes still arrive, and the one rAF-batched store
(workloads) flushes on the first frame after the window is shown.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Can GULDOGAN <cguldogan@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant