IOAccelerator GPU memory leak: idle sessions accumulate ~1 GB non-reclaimable footprint each
Summary
Long-lived Claude Code sessions accumulate 700–968 MB of non-reclaimable IOAccelerator (GPU) dirty pages that are never freed. This is invisible to RSS monitoring (7 MB RSS vs 1.3 GB footprint — 15× underestimate) but triggers macOS "out of memory" warnings attributed to the parent terminal. On a 32 GB machine with 37 idle sessions, this totals ~41 GB of memory pressure from GPU buffers alone.
Root Cause
Claude Code uses Ink (React for terminals) on Bun (JSC/WebKit). The rendering pipeline goes through WebKit's GPU compositor, which allocates IOAccelerator 128 MB buffer slabs. These slabs grow monotonically during the session lifetime and are never freed or reused.
Ink React render → Yoga layout → JSC/WebKit compositor → IOAccelerator GPU buffers (128 MB slabs, never freed)
This is confirmed to be Claude Code-specific (Ink rendering), not Bun baseline. Plain Bun processes stay at ~1.3 MB IOAccelerator. Claude Code sessions grow to 10 slabs (966 MB) over days.
Reproduction
- Start Claude Code:
claude - Use it actively for 1+ hours
- Check:
footprint -p $(pgrep -f 'claude' | head -1) - Observe
IOAcceleratorgrowing in 128 MB increments - Leave idle — IOAccelerator dominates footprint, never shrinks
Control
echo "await Bun.sleep(3600000);" | bun run -
# footprint shows IOAccelerator stays at ~1.3 MB
Evidence
Footprint breakdown — idle session (PID 29561, 15 days old)
Footprint: 1324 MB (RSS: 7 MB)
968 MB IOAccelerator ← 73% of footprint, GPU dirty pages
265 MB WebKit malloc ← JS heap
37 MB JS VM Gigacage
24 MB MALLOC_SMALL
18 MB JS JIT generated code
IOAccelerator slab structure (vmmap)
54db4000000-54dbc000000 128.0M swap: 95.7M ← oldest, nearly full
54dbc000000-54dc4000000 128.0M swap: 95.3M
54dc4000000-54dcc000000 128.0M swap: 126.3M
54dcc000000-54dd4000000 128.0M swap: 99.7M
54dd4000000-54ddc000000 128.0M swap: 127.5M
54ddc000000-54de4000000 128.0M swap: 127.5M
54de4000000-54dec000000 128.0M swap: 122.9M
54dec000000-54df4000000 128.0M swap: 106.1M
54df4000000-54dfc000000 128.0M swap: 65.0M
54dfc000000-54e04000000 128.0M swap: 80K ← newest
(reserved) 768.0M ← pre-allocated for future slabs
10 × 128 MB slabs, all dirty, non-reclaimable. Peak footprint was 2.8 GB.
Growth by session age
| Session State | IOAccel Slabs | IOAccel Dirty | Total Footprint | RSS |
|---------------|--------------|---------------|-----------------|-----|
| Fresh bun (no Ink) | 1 | 1.3 MB | 6.5 MB | 5 MB |
| Claude Code (3 hours) | 4 | 46 MB | 443 MB | 393 MB |
| Claude Code (8 days idle) | ~8 | 711 MB | 996 MB | 8 MB |
| Claude Code (15 days idle) | 10 | 966 MB | 1324 MB | 7 MB |
System-wide impact (37 sessions on 32 GB machine)
- Total footprint: 62.7 GB (vs 4.1 GB RSS)
- macOS memory pressure: 41% free
- Compressed pages: 14.6 GB
- macOS showed "iTerm2 using 64 GB" (all claude descendants attributed to parent)
Additional: leaks tool detected 175,613 leaked objects
Process 29561: 175613 leaks for 13551072 total leaked bytes.
(Standard malloc zone only; WebKit malloc zone unreadable due to security restrictions.)
Environment
- OS: macOS 26.3 (25D125), Apple Silicon
- Claude Code: 2.1.78
- Runtime: Bun (JSC/WebKit), confirmed via binary strings and memory categories
- Terminal: iTerm2 3.6.6
- RAM: 32 GB
Measurement Commands
# Real footprint (what macOS uses for memory warnings)
footprint -p <pid>
# IOAccelerator slab details
vmmap -summary <pid> | grep IOAccel
# System memory pressure
sysctl -n kern.memorystatus_level
# Compare: RSS understates by 15×
ps -o pid,rss -p <pid> # 7 MB (lies)
footprint -p <pid> # 1324 MB (truth)
Suggested Mitigations
- Periodic GPU buffer release: Investigate if IOAccelerator slabs can be explicitly freed when the session is idle
- Compositor opt-out: Explore whether Bun's JSC/WebKit compositor can be disabled for terminal rendering (Ink does not need GPU compositing)
- Session recycling: Long-idle sessions could be offered for cleanup/restart
- Documentation: Note that
footprint, not RSS, reflects actual memory cost on macOS
Related Issues
- #24113 — IOAccelerator observed at 2.3 GB, but retracted (attributed to Ghostty)
- #33453 — WebKit Malloc growth (different category, same runtime)
- #18859 — 15 GB per idle session (same symptom, root cause not identified)
- #33589 — ArrayBuffer accumulation (different root cause)
- oven-sh/bun#21560 — RSS grows while JS heap flat (GPU cause not identified)
Full deep-dive analysis with raw data and reproduction methodology is available upon request.
This issue has 7 comments on GitHub. Read the full discussion on GitHub ↗