perf(terminal): use WebGL renderer and batched writes#2680
Conversation
The terminal ran on xterm's default DOM renderer and wrote every pty
chunk synchronously, so heavy output (build logs, large files) pinned
the renderer.
- Load the WebGL addon after term.open(), with an onContextLoss handler
that disposes it so xterm falls back to the DOM renderer instead of
rendering nothing, and a try/catch fallback when WebGL is unavailable.
- Coalesce pty output into one term.write() per animation frame; flush
the buffer before serializing on detach and cancel the pending frame
on destroy.
Also restore the execute bit on node-pty's spawn-helper in the Electron
postinstall: pnpm extracts the prebuilt binary as 0644, which makes
posix_spawnp fail ("posix_spawnp failed") the first time a terminal
session opens after a fresh install.
Adds a "GPU rendering" toggle to terminal settings (default on). When disabled, TerminalManager disposes the WebGL addon so xterm falls back to its DOM renderer; toggling applies live to open terminals. Persisted via the settings store and synced into TerminalManager like theme and font. Generated-By: PostHog Code Task-Id: 177e4a61-ddc5-440a-8f9b-81d043f41335
|
React Doctor found no issues in the changed files. 🎉 Reviewed by React Doctor for commit |
|
Fix the writeData comment, which claimed term.write() was synchronous and reflowed per IPC chunk; xterm buffers writes and RAF-debounces rendering, so the batching actually trims per-call parse/write-buffer overhead. Also soften "dramatically slower" and an unverified 0644 mode claim in postinstall. Generated-By: PostHog Code Task-Id: 177e4a61-ddc5-440a-8f9b-81d043f41335
|
Reviews (2): Last reviewed commit: "docs(terminal): correct write-batching a..." | Re-trigger Greptile |
There was a problem hiding this comment.
Pull request overview
This PR improves terminal rendering performance under heavy output by enabling xterm’s WebGL renderer (with a user-facing toggle) and batching terminal writes, and it also patches a node-pty postinstall issue where spawn-helper can lose its executable bit under pnpm.
Changes:
- Add
@xterm/addon-webgland load aWebglAddonafterterm.open()to enable GPU-accelerated rendering, with runtime toggling viaterminalManager.setUseWebgl. - Batch
writeDatacalls per animation frame to reduce xterm parse/write churn during high-volume output. - Persist a new
terminalGpuRenderingsetting, expose it in UI settings, and restorenode-ptyspawn-helperexecutability inpostinstall.
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Locks @xterm/addon-webgl and associated dependency updates. |
| packages/ui/src/features/terminal/TerminalManager.ts | Adds WebGL addon lifecycle management and per-frame batched writes. |
| packages/ui/src/features/terminal/Terminal.tsx | Syncs the persisted GPU-rendering setting into terminalManager. |
| packages/ui/src/features/settings/settingsStore.ts | Adds/persists terminalGpuRendering setting and setter. |
| packages/ui/src/features/settings/sections/TerminalSettings.tsx | Adds “GPU rendering” toggle UI and analytics event. |
| packages/ui/package.json | Adds @xterm/addon-webgl dependency. |
| apps/code/scripts/postinstall.sh | Restores +x on node-pty prebuilt spawn-helper binaries. |
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Coalesce bursts of pty output into a single term.write() per animation | ||
| // frame instead of one call per IPC chunk, cutting the per-call parse and | ||
| // write-buffer overhead that piles up on the main thread under a heavy | ||
| // stream (build logs, cat-ing a file). | ||
| instance.writeBuffer += data; |
| if (instance.flushHandle === null) { | ||
| instance.flushHandle = requestAnimationFrame(() => { | ||
| instance.flushHandle = null; | ||
| this.flushWrite(sessionId, instance); | ||
| }); |
| // Terminal | ||
| terminalFont: state.terminalFont, | ||
| terminalCustomFontFamily: state.terminalCustomFontFamily, | ||
| terminalGpuRendering: state.terminalGpuRendering, | ||
|
|
|
Reviews (3): Last reviewed commit: "docs(terminal): correct write-batching a..." | Re-trigger Greptile |
Problem
Under heavy output load, the terminal renderer could feel sluggish. We want smoother rendering by leveraging GPU-accelerated WebGL output, while still giving users an escape hatch in case of graphical glitches on their hardware.
Changes
WebGL rendering for the terminal
@xterm/addon-webgldependency topackages/ui.TerminalManagernow creates and manages aWebglAddonper terminal instance, trackingwebglAddon,writeBuffer, andflushHandleon eachTerminalInstance.setUseWebglcapability and an internaluseWebglflag (defaults totrue) so rendering mode can be toggled at runtime.GPU rendering setting
terminalGpuRenderingboolean to the settings store (defaults totrue), with asetTerminalGpuRenderingsetter, and persisted it across sessions.Switch) inTerminalSettings, with an analytics event fired on change.Terminal.tsxsyncs the setting toterminalManager.setUseWebgl(...).noBorderusage on the existing font setting rows now that the GPU row is the last item.Native module fix (postinstall)
node-pty'sspawn-helperprebuilt binaries duringpostinstall, fixingposix_spawnp failederrors when opening a terminal session (pnpm drops the executable mode on extraction).How did you test this?
Automatic notifications
Created with PostHog Code