[PR #13594] fix: address 6 memory leaks for long-running sessions #14729

Open
opened 2026-02-16 18:19:29 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/anomalyco/opencode/pull/13594

State: open
Merged: No


Summary

Fixes 6 memory leaks that cause RSS to grow to multi-GB levels during long-running sessions.

Changes

  1. queue.ts — AsyncQueue termination

    • Added close() and drain() methods with DONE sentinel symbol
    • [Symbol.asyncIterator] now breaks on close instead of looping forever
    • Prevents leaked promises and unbounded queue growth
  2. bash.ts — Output buffer cap

    • Replaced output += chunk.toString() with Buffer[] ring buffer
    • 10 MB hard cap; oldest chunks evicted when exceeded
    • Eliminates O(n²) string concatenation and caps memory for long commands
  3. lsp/client.ts — Diagnostics Map cleanup

    • diagnostics.clear() on shutdown()
    • LRU eviction when Map exceeds 5,000 entries (delete-before-set pattern)
    • Prevents unbounded Map growth in large workspaces
  4. bus/index.ts — Subscription cleanup on dispose

    • subscriptions.clear() in dispose callback after notifying wildcard listeners
    • Prevents subscription array leak across instance lifecycle
  5. pty/index.ts — Buffer chunking

    • Replaced buffer: string with bufferChunks: string[] + bufferLen tracker
    • Chunk-based eviction instead of string.slice() on every write
    • Reduces GC pressure from repeated large string allocations
  6. index.ts — Shutdown resource cleanup

    • Added Instance.disposeAll() in finally block
    • Ensures all instance-scoped resources (LSP clients, bus, PTY sessions) are released on exit

Test plan

  • bunx tsc --noEmit — zero type errors
  • Full turbo typecheck across all 12 packages — all pass
  • Manual: run opencode for extended session, verify RSS stays stable

Closes #10913

🤖 Generated with Claude Code

**Original Pull Request:** https://github.com/anomalyco/opencode/pull/13594 **State:** open **Merged:** No --- ## Summary Fixes 6 memory leaks that cause RSS to grow to multi-GB levels during long-running sessions. ### Changes 1. **`queue.ts` — AsyncQueue termination** - Added `close()` and `drain()` methods with `DONE` sentinel symbol - `[Symbol.asyncIterator]` now breaks on close instead of looping forever - Prevents leaked promises and unbounded queue growth 2. **`bash.ts` — Output buffer cap** - Replaced `output += chunk.toString()` with `Buffer[]` ring buffer - 10 MB hard cap; oldest chunks evicted when exceeded - Eliminates O(n²) string concatenation and caps memory for long commands 3. **`lsp/client.ts` — Diagnostics Map cleanup** - `diagnostics.clear()` on `shutdown()` - LRU eviction when Map exceeds 5,000 entries (delete-before-set pattern) - Prevents unbounded Map growth in large workspaces 4. **`bus/index.ts` — Subscription cleanup on dispose** - `subscriptions.clear()` in dispose callback after notifying wildcard listeners - Prevents subscription array leak across instance lifecycle 5. **`pty/index.ts` — Buffer chunking** - Replaced `buffer: string` with `bufferChunks: string[]` + `bufferLen` tracker - Chunk-based eviction instead of `string.slice()` on every write - Reduces GC pressure from repeated large string allocations 6. **`index.ts` — Shutdown resource cleanup** - Added `Instance.disposeAll()` in `finally` block - Ensures all instance-scoped resources (LSP clients, bus, PTY sessions) are released on exit ## Test plan - [x] `bunx tsc --noEmit` — zero type errors - [x] Full `turbo typecheck` across all 12 packages — all pass - [ ] Manual: run opencode for extended session, verify RSS stays stable Closes #10913 🤖 Generated with [Claude Code](https://claude.com/claude-code)
yindo added the pull-request label 2026-02-16 18:19:29 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#14729