IOAccelerator GPU leak is version-dependent, not session-lifetime-dependent: 2.1.14x clean, 2.1.217+ leaks (2.77 GB across 37 sessions)
IOAccelerator GPU leak is version-dependent, not session-lifetime-dependent: 2.1.14x clean, 2.1.217+ leaks (2.77 GB across 37 sessions)
Summary
Re-filing per the close message on #35804 (closed NOT_PLANNED 2026-04-16 by the inactivity bot, now locked). The IOAccelerator leak it described is still present in 2.1.220, five months later.
New evidence this report adds: the leak correlates with the Claude Code version, not with session lifetime or CPU activity. #35804 modeled it as monotonic growth over a session's life. That model does not hold — on this machine the two oldest and busiest processes are the two cleanest.
Environment
- Apple M4 Mac mini, 24 GB unified memory
- macOS 26.4.1 (25E253)
- Claude Code 2.1.141, 2.1.145, 2.1.217, 2.1.218, 2.1.220 running concurrently (37 processes)
- All installed builds 2.1.217–2.1.221 bundle Bun 1.4.0 (verified via
strings)
The version boundary
IOAccelerator dirty pages, from vmmap -summary <pid>:
| Version | Procs | Total IOAccel dirty | Mean per proc |
|---|---|---|---|
| 2.1.141 | 2 | 1.27 MB | 0.63 MB |
| 2.1.145 | 2 | 1.41 MB | 0.70 MB |
| 2.1.217 | 4 | 375.3 MB | 93.8 MB |
| 2.1.218 | 3 | 219.4 MB | 73.1 MB |
| 2.1.220 | 26 | 2176.6 MB | 83.7 MB |
| Total | 37 | 2774 MB | |
Every 2.1.14x process is under 1 MB. Every 2.1.217+ process is 16–331 MB. No overlap between the two groups.
Ruling out lifetime and activity
If the leak were driven by session age or render volume, the oldest/busiest processes would be the worst. They are the best:
| PID | Version | CPU time | Elapsed | IOAccel dirty |
|---|---|---|---|---|
| 37566 | 2.1.145 | 707 min | 75 days | 720 KB |
| 7314 | 2.1.141 | 178 min | 81 days | 640 KB |
| 54797 | 2.1.141 | 168 min | 81 days | 656 KB |
| 40861 | 2.1.145 | 150 min | 75 days | 720 KB |
| 27792 | 2.1.220 | 1.3 min | 1 hour | 89.3 MB |
| 37916 | 2.1.220 | 1.5 min | 2.6 hours | 31.6 MB |
| 3672 | 2.1.220 | 7.2 min | 1.2 days | 108.3 MB |
| 83449 | 2.1.220 | 100 min | 3.8 days | 330.7 MB |
PID 37566 has consumed 540× more CPU than PID 27792 and holds 1/124th the GPU memory.
Within 2.1.220 the value jumps to roughly 90 MB early — PID 27792 reached 89.3 MB after one hour and 1.3 minutes of CPU — then varies without a clean correlation to either axis.
Per-process breakdown
vmmap -summary 83449 (2.1.220, 486 MB footprint):
REGION TYPE VIRTUAL RESIDENT DIRTY SWAPPED
IOAccelerator 900.5M 365.1M 336.0M 102.5M
__TEXT 632.5M 185.3M 0K 0K
JS JIT generated code 64.0M 20.8M 20.8M 14.5M
JS VM Gigacage 128.0M 7040K 7040K 544K
MALLOC_SMALL 40.0M 1920K 1920K 7696K
325 MB of the 355.7 MB total dirty is IOAccelerator — 91%. The actual JS heap is 7 MB. The conversation is not what costs memory.
System impact
With 37 sessions on a 24 GB machine:
PhysMem: 23G used (2883M wired, 10G compressor), 152M unused
vm.swapusage: total = 15360.00M used = 14168.94M free = 1191.06M
Reproduction
# per-process
vmmap -summary $(pgrep -f 'local/bin/claude' | head -1) | grep -E 'IOAccelerator|Physical footprint'
# fleet-wide total
for p in $(pgrep -f "local/bin/claude"); do
vmmap -summary $p 2>/dev/null | awk '$1=="IOAccelerator" && $2!="(reserved)"{print $4}'
done
RSS does not show this. ps reported 459 MB for PID 83449 against a 486 MB footprint with 325 MB of it GPU-dirty; on lighter sessions the RSS gap is far wider. Use footprint -p or vmmap -summary.
Why the version data matters
The bundled Bun is 1.4.0 for every build I still have on disk (2.1.217–2.1.221), so the regression is not a Bun bump inside that window. The 2.1.141 and 2.1.145 binaries have been pruned from ~/.local/share/claude/versions/, so I cannot check what they shipped — the processes hold deleted images. If those builds carried an older Bun, the bisect target is the Bun upgrade; if not, it is a change in Claude Code's own render path between 2.1.145 and 2.1.217.
Either way the earlier builds demonstrate the leak is not inherent to Ink-on-Bun: a 75-day 2.1.145 session with 707 minutes of CPU sits at 720 KB.
References
- #35804 — original report, closed
NOT_PLANNEDby the inactivity bot, locked. Close message directs re-filing. - oven-sh/bun#28234 — upstream, still OPEN. Isolated a minimal Ink/React repro on Bun.
- #24113 — retracted, attributed to a Ghostty terminal bug. Distinct: this allocation is inside the
claudeprocess.