-
Notifications
You must be signed in to change notification settings - Fork 11.2k
Description
Summary
Each OpenCode session spawns its own copies of MCP servers and LSP instances, even when multiple sessions operate on the same project. With 3 concurrent sessions on the same codebase, this results in significant memory duplication that compounds the known unbounded-cache memory growth (#9140, #5363).
Environment
- opencode version: 1.1.54 (Bun-compiled, darwin-arm64)
- OS: macOS, Apple Silicon, 64GB RAM
- Sessions: 3 concurrent TUI sessions on the same project
Observed Behavior
Per-session process duplication
With 3 OpenCode sessions running against the same project, ps shows:
| Parent PID | Child Process | RSS | Notes |
|---|---|---|---|
| 42568 | osgrep mcp |
73MB | Session 1 |
| 42568 | bash-language-server |
40MB | Session 1 |
| 43045 | osgrep mcp |
48MB | Session 2 |
| 43045 | typescript-language-server (x3) |
40MB each | Session 2 — 3 separate instances |
| 80231 | osgrep mcp |
557MB | Session 3 — same MCP, 7.6x the others |
3 separate osgrep mcp processes serving the same index for the same project — ~678MB combined for what could be a single shared daemon.
3 separate typescript-language-server instances spawned by a single session (PID 43045), plus the bash-language-server — ~160MB for LSPs that could share state.
Memory profile of the main processes
| PID | Uptime | RSS | %CPU | Role |
|---|---|---|---|---|
| 42568 | 76 min | 2.9GB | 114% | Active session (heavy use) |
| 43045 | 76 min | 700MB | 13% | Active session |
| 80231 | 1.5 min | 525MB | 14% | Fresh session |
System impact
- Physical RAM: 63GB used, 288MB free (of 64GB)
- Compressor: 34GB (macOS compressing half of RAM in-memory)
- Swap: 1.3GB / 2GB used
- Load average: 58 / 48 / 51 on a 10-core machine (5-6x oversubscribed)
The memory pressure from duplication forces macOS into heavy compression and swap, which then causes CPU overhead from compress/decompress cycles — a cascading performance degradation.
Proposed Improvements
1. Shared MCP server daemon (high impact)
MCP servers like osgrep maintain an index of the project. Multiple sessions querying the same project should connect to a single shared MCP server process rather than each spawning their own.
Architecture: first session spawns the MCP server and writes a socket/port to a lockfile; subsequent sessions connect to the existing instance. Graceful shutdown when the last session disconnects.
2. Shared LSP server pool (medium impact)
Language servers for the same project/workspace should be shared across sessions, similar to how VS Code shares a single LSP instance across multiple editor tabs.
3. osgrep MCP memory variance
The 3 osgrep mcp instances showed wildly different RSS (73MB, 48MB, 557MB) despite serving the same project. This suggests either a leak within osgrep's MCP mode or inconsistent GC behavior worth investigating.
Related Issues
- Memory leak: Unbounded caches grow without limit #9140 — Unbounded caches grow without limit (compounds this)
- opencode eating 70gb of memory? #5363 — 70GB memory usage
- Opencode processes survive terminal disconnect, become orphans, and leak memory #12913 — Orphan processes leak memory
opencodeprocess orphans when its parent exits #13001 — Process orphans when parent exits- [FEATURE]: Deactivate unused LSP servers during a session #12976 — Feature request to deactivate unused LSP servers
This issue is distinct from the above: it's about duplication across concurrent sessions, not growth within a single session or orphan cleanup. Fixing the shared-daemon pattern would reduce the baseline memory footprint proportionally to the number of concurrent sessions.