Skip to content

Massive CPU consumption due to rendering #6822

Open

Description

@Nostromos

Where did this happen?

Desktop app (macOS)

Version

1.24.2

What happened?

Image

Steps to reproduce

Will get repro steps and screenshots/recordings/logs/etc.

For the record I updated to the newest macos version over the weekend

Logs, screenshots, or recordings

Will get repro steps and screenshots/recordings/logs/etc.

For the record I updated to the newest macos version over the weekend

Activity

  1. github-actions commented on Aug 24, 2026

    @github-actions
    Contributor

    Triage notes

    Summary. This reports high CPU on the macOS desktop app at v1.24.2, attributed to rendering, with a screenshot as the only evidence and repro steps promised in a follow-up. The reporter also notes they updated macOS over the weekend — worth keeping, because several of the app's most CPU-sensitive paths are macOS-version- and GPU-driver-sensitive by design. I couldn't fetch the attached image (no network access from triage), so everything below is derived from reading the code rather than from the screenshot; the version reported matches apps/desktop/package.json:5 at HEAD, so the code paths cited are the ones the reporter is running.

    Most likely code paths

    Ranked by how well they fit "massive CPU, rendering, macOS, right after an OS update":

    1. WebGL → DOM renderer fallback for terminals is sticky and silent. apps/desktop/src/renderer/lib/terminal/terminal-addons.ts:19-20 holds suggestedRendererType at module scope. On a WebGL context loss, apps/desktop/src/renderer/lib/terminal/terminal-addons.ts:80-85 disposes the addon and latches "dom", and apps/desktop/src/renderer/lib/terminal/terminal-addons.ts:76 then skips WebGL for every terminal created afterwards, for the remainder of the app session. Construction failure does the same at :97-99. The xterm DOM renderer is roughly an order of magnitude more expensive per frame than WebGL, so a single context loss converts every terminal in the window into a CPU-heavy renderer with no user-visible signal and no recovery short of restarting the app. A macOS update changing GPU drivers or Chromium's feature blocklist is exactly the trigger class for that first context loss. This is my leading hypothesis.

    2. Background throttling is disabled on macOS, so nothing idles down. apps/desktop/src/main/windows/main.ts:405-408 calls setBackgroundThrottling(false) for all macOS windows (deliberately — the comment cites Sequoia+ compositor-layer corruption). The cost is that every always-running animation keeps painting at full rate even when the window is occluded or backgrounded: the per-row braille spinners at 12.5 fps (apps/desktop/src/renderer/screens/main/components/AsciiSpinner/AsciiSpinner.tsx:21-27, one interval per animating row), the updates pill (apps/desktop/src/renderer/components/UpdatesPill/UpdatesPill.tsx:26-33), blinking terminal cursors (cursorBlink: true by default, apps/desktop/src/renderer/screens/main/components/WorkspaceView/ContentView/TabsContent/Terminal/config.ts:26), and CSS animate-* usage across ~80 renderer files. On its own this is a raised floor, not a spike — but it multiplies hypothesis 1 and 3.

    3. A crash-looping GPU process turns into a resize storm. apps/desktop/src/main/windows/main.ts:102-108 responds to child-process-gone for the GPU by calling forceRepaint, which at apps/desktop/src/main/windows/main.ts:90-99 resizes the window by one pixel and back 32 ms later. Each of those two resizes fires the per-terminal ResizeObserver (apps/desktop/src/renderer/lib/terminal/terminal-runtime.ts:407-409), which debounces 75 ms and then runs a full fitAddon.fit() + terminal.refresh(0, rows-1) + PTY resize with forceNotify: true for every attached terminal (apps/desktop/src/renderer/lib/terminal/terminal-runtime.ts:216-296). There's no rate limit or backoff on the handler, so if the GPU process is restarting repeatedly after an OS update, the app relayouts and repaints every terminal on every restart. webContents.invalidate() on show/restore (apps/desktop/src/main/windows/main.ts:446-454) is in the same family but is event-bounded and much less likely to be the cause.

    Ruled out as the primary cause: PTY output volume. apps/desktop/src/renderer/lib/terminal/write-coalescer.ts already batches writes to one xterm.write() per animation frame with a 1 MB synchronous-flush ceiling, so chunk-rate alone shouldn't scale CPU. Similarly, the resource monitor's 2 s poll (.../ResourceConsumption/hooks/useResourceSnapshot/useResourceSnapshot.ts:126-140) drives ps-based process-tree scans in the main process (apps/desktop/src/main/lib/resource-metrics/index.ts:257-288) — real cost if the Resources popover or Usage page is left open, but it would show up as main-process CPU, not rendering.

    What would confirm which one

    The single most useful datum is which process is burning CPU. From the reporter:

    • Activity Monitor, expanded: is it Superset Helper (Renderer), Superset Helper (GPU), or the main Superset process? Equivalently, the app's own Resources popover splits this into Main / Renderer / Other (.../ResourceConsumption/components/AppResourceSection/AppResourceSection.tsx:65-84).
    • chrome://gpu from the renderer devtools (or app.getGPUFeatureStatus()): is WebGL hardware-accelerated or software/disabled? If disabled, hypothesis 1 is confirmed.
    • Renderer console filtered for GPU context-loss warnings, plus main-process logs for [main-window] GPU process gone: — a repeating line there confirms hypothesis 3.
    • Does CPU stay high with all terminals closed but the app open, and does it drop after quitting and relaunching? A restart-clears-it signature points squarely at the latched suggestedRendererType.

    For a maintainer-side repro of hypothesis 1 without waiting on the reporter: open a workspace with a few terminals, force a context loss on one (devtools: WEBGL_lose_context.loseContext() on the xterm canvas, or run with --disable-gpu), then open new terminals and profile. Expected buggy behaviour: the new terminals also render via DOM and renderer CPU stays elevated indefinitely. A bun:test unit repro is possible but shallow — the observable contract is just that loadAddons stops attempting WebGL after one onContextLoss; asserting that against a fake XTerm documents the latch, but the CPU claim itself needs a profile.

    Fix direction

    For the latch: scope suggestedRendererType per window/session rather than per module, and add a bounded retry (e.g. re-attempt WebGL on the next terminal creation, giving up only after N losses) so one transient driver hiccup doesn't degrade the whole session. At minimum, log the fallback and surface it — a silent 10× rendering-cost change is invisible to both users and to us in bug reports like this one. For the GPU-gone handler, add a backoff/cap so a crash loop can't drive an unbounded resize storm through every terminal's ResizeObserver. The setBackgroundThrottling(false) call is load-bearing for a real Sequoia bug and shouldn't be reverted blind; if it turns out to matter here, the narrower fix is pausing the interval-driven animations on visibilitychange/window blur rather than re-enabling throttling.

    Marking this as needing the promised repro steps plus the process-level CPU breakdown before anyone starts on a fix — the three hypotheses have quite different fixes and the screenshot alone doesn't discriminate between them.

  2. mustvlad commented on Sep 21, 2026

    @mustvlad

    Is this going to be solved? I get massive CPU spikes on my M1 max since the new versions of Superset. And I always find this Superset Rendered affecting it.

  3. arataoka commented on Sep 29, 2026

    @arataoka

    Still happening on 1.31.0 (latest), macOS 26.2 arm64, 64 GB RAM. In my case memory grows along with CPU, and it starts right at launch.

    Renderer RSS / CPU after a normal app launch (sampled every 10 s, no crash involved):

    • 0:15 — 2.9 GB, 118%
    • 0:35 — 7.6 GB, 103%
    • 1:05 — 9.9 GB, 112%
    • 1:15 — 9.8 GB, 632%

    A previous session's renderer was at 12.8 GB RSS / 268% CPU after 23 minutes.

    Other notes:

    • Only Superset Helper (Renderer) grows. host-service (~580 MB) and pty-daemon (~150 MB) look normal.
    • A Codex agent was running in one workspace at the time.
    • main.log shows no renderer crash in this session.
    • Hypothesis: the growth is front-loaded rather than a slow leak, so something restored at startup (terminal scrollback or workspace state) may be loaded all at once.

    Possibly related: #5921 (long-uptime renderer CPU) and #5320 (renderer heap blow-up on workspace open).

  4. matejshovels commented on Oct 21, 2026

    @matejshovels

    I see the same high renderer CPU on 1.33.0. The triage comment above asks which process and which thread use the CPU, so here is that breakdown.

    Environment: Superset 1.33.0 (Electron 41.10.3), macOS 26.5, M5 Max, 36 GB. The app had been running for 15 days, with about 14 Claude Code sessions in terminals across several workspaces.

    Which process: Superset Helper (Renderer). Over the 15 days it used about 2,130 CPU-minutes. The GPU helper used 202 and the main process 49.

    Which thread: a 5-second sample of the renderer while it sat at about 100% CPU:

    • Compositor thread: busy in 3,868 of 4,031 samples (96%).
    • Main thread: waiting in mach_msg in 3,442 of 4,031 samples (85% idle).

    So the load sits in the compositor, not on the main thread.

    Over a day: I sampled Superset's CPU every 30 seconds for about 10 hours. The median was 16% and the 90th percentile was 110%. During 2 hours with the laptop awake and me away, it idled at 2 to 3%. So it does not stay pegged the way #5921 describes. It is high during the hours I work, with hourly means of 50 to 110%.

    GPU process restarts: main.log has no GPU process gone lines since Aug 19, so the GPU crash loop does not seem to apply here.

    Not checked yet: the WebGL status in chrome://gpu, CPU with all terminals closed, and whether a relaunch clears it. I will post an update once I upgrade to newest Superset version.

    2026-10-20-superset-renderer-sample.txt

    The full sample output is attached.

  5. matejshovels commented on Oct 22, 2026

    @matejshovels

    The issue stayed on 1.39. I opened a PR with a fix.

    Everyone welcome to upvote it, so it gets merged faster.

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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions