Per-session MCP server and LSP duplication multiplies memory usage across concurrent sessions #9015

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

Originally created by @marcusquinn on GitHub (Feb 10, 2026).

Originally assigned to: @thdxr on GitHub.

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

  • #9140 — Unbounded caches grow without limit (compounds this)
  • #5363 — 70GB memory usage
  • #12913 — Orphan processes leak memory
  • #13001 — Process orphans when parent exits
  • #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.

Originally created by @marcusquinn on GitHub (Feb 10, 2026). Originally assigned to: @thdxr on GitHub. ## 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 - #9140 — Unbounded caches grow without limit (compounds this) - #5363 — 70GB memory usage - #12913 — Orphan processes leak memory - #13001 — Process orphans when parent exits - #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.
yindo added the perf label 2026-02-16 18:11:24 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#9015