Skip to content

Free a hidden pane's WebGL renderer until it is shown again - #32

Merged
YogiOnCode merged 1 commit into
mainfrom
perf/webgl-visible-pane
Oct 20, 2026
Merged

YogiOnCode merged 1 commit into
mainfrom
perf/webgl-visible-pane

Conversation

@YogiOnCode

Copy link
Copy Markdown
Owner

Clayo uses less memory with several sessions open: a pane you can't see now gives its GPU memory back until you switch to it.

What changes

  • Every open pane used to keep xterm.js's WebGL renderer, hidden ones too. Each held its own context and glyph textures in the WebView2 GPU process.
  • Now only the visible pane keeps it. A hidden pane falls back to the DOM renderer, which draws nothing while hidden, and gets WebGL back when shown.
  • TerminalPane tells the page when it is shown or hidden: another session picked, Settings open, window hidden to the tray. It also tells it once the page is ready, for a pane that was hidden before then.
  • Output, scrollback, typing and the status light keep running in hidden panes as before.

Measured

Debug builds, idle Claude Code sessions, own WebView2 folder, private working set of the GPU process. This PC has Intel integrated graphics only, so this memory is system RAM.

Panes Before After
4 216 MB ~190 MB
8 381 MB ~281 MB
  • The saving is ~13 MB per hidden pane, not the full ~30 MB its WebGL costs: the GPU process keeps some freed memory and reuses it. Forcing WEBGL_lose_context made no difference, so it isn't used.
  • While switching panes rapidly (every 250 ms), memory goes up to ~298 MB for a moment, then settles back within 10 s.

Testing

  • dotnet build and dotnet build -c Release with -warnaserror give 0 warnings and 0 errors. scripts/checks.ps1 passes all 19 checks.
  • Checked through the page title during a run: the visible pane on WebGL, the hidden ones on DOM with no canvas.
  • Switched between 4 panes 20 times through UI Automation. Memory stayed flat, and screenshots showed each pane fully painted 120 ms after being shown.
  • Not tested: output arriving while a pane is hidden (the test sessions were idle), and opening Settings or hiding to the tray (same signal, not driven).

Every open pane kept xterm.js's WebGL renderer, hidden ones too, each
with its own context and glyph textures in the WebView2 GPU process.
A pane you can't see draws nothing, so it now drops the renderer and
falls back to the DOM one until it is shown.

TerminalPane posts "gpu" on IsVisibleChanged (another session picked,
Settings open, window hidden to the tray), and once on "ready" for a
pane that was hidden before its page was up.

Measured with idle sessions, private working set of the GPU process:
4 panes 216 -> ~190 MB, 8 panes 381 -> ~281 MB. Switching panes 20
rounds showed no growth, and each pane painted fully 120 ms after
being shown.
@YogiOnCode
YogiOnCode merged commit 3d1b13d into main Oct 20, 2026
1 check passed
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