Agents window: background session terminals keep their renderer-side xterm alive, growing unbounded
- Dominant language
- TypeScript
- Stars
- 193k
- Forks
- 42.4k
- PR merge metrics
- PR metrics pending
Description
Found while analyzing a renderer heap snapshot from the Agents window (484 MB self-size).
## Summary
**80 MB (~16% of the renderer heap)** was xterm buffer data: 10,791 `JSArrayBufferData` allocations traced to `xterm ... _core._inputHandler._activeBuffer.lines._array[]._data → Uint32Array`.
There were **38 live `XtermTerminal` instances** (76 `_activeBuffer` roots = 38 terminals × normal + alternate buffer), which matches `SessionsTerminalContribution` exactly: ~33 entries in `_sessionTerminals` plus ~7 in `_standaloneTerminalIds`.
## This is by design, but it doesn't scale
`SessionsTerminalContribution` (`src/vs/sessions/contrib/terminal/browser/sessionsTerminalContribution.ts`) distinguishes two paths:
- **Session removed** → `_closeTerminalsForSession` → `safeDisposeTerminal` (pty torn down).
- **Session archived / "Mark as Done"** → `_hideTerminalsForSession` → `_terminalService.moveToBackground` — deliberately keeps both the pty *and* the frontend xterm alive so unarchiving is instant.
Since archiving is the common flow and removal is rare, the live xterm count grows monotonically with the number of sessions ever opened, at roughly **1 MB each** (default 1000-line scrollback × cols × 4 bytes per cell).
At 38 sessions this is 80 MB. Someone with a few hundred archived sessions would be well into the hundreds of MB, purely in renderer-side scrollback for terminals that aren't visible.
## Options
1. **Release the renderer-side xterm for backgrounded terminals, keep the pty.** The pty host already replays scrollback on re-attach, so the content is recoverable. This is the correct fix but requires teaching `TerminalInstance` to drop `_xterm` when moved to background and lazily recreate it, which touches shared terminal code.
2. **LRU cap on background session terminals.** Keep the N most recently used xterms hydrated, dispose the rest. Cheaper, bounded, and mostly invisible in practice.
3. **Lower scrollback for backgrounded terminals.** Cheapest stopgap, proportional rather than bounded savings.
## Effort estimate
Medium. Option 2 is contained within `sessionsTerminalContribution.ts`; option 1 is the real fix but spans `vs/workbench/contrib/terminal`.
Lowest priority of the three memory issues from this snapshot — it's a design tradeoff rather than a leak, and 80 MB is the smallest of the three.
(Written by Copilot)
Contributor guide
Assessment
This issue has not been assessed yet.