Repository navigation
fix(server): bound loaded preamble states with an LRU - #521
Conversation
pch_cache's PreambleState blobs (mmap of the paired index, tens of MB per distinct preamble key on real projects) were opened on first use and retained for the server's lifetime: didClose, idle time and store eviction all failed to release them, so memory grew with every preamble key ever touched. - Workspace keeps a loaded-state LRU, budgeted at open documents + 2 (provider wired by the master; the slack keeps a just-closed state warm for quick reopen). Loads and rebuilds touch the LRU; didClose shrinks the budget and enforces it. Unloading only drops the cache's reference — consumers hold shared_ptr copies and finish safely, and the next use reopens the blob from disk. - CacheStore records blobs its LRU evicts (copied before the entry erase — ASan caught a use-after-free in an earlier draft) and the master drains the records on its checkpoint task, dropping orphaned pch_cache metadata only when the store still lacks the blob, so a key rebuilt after the eviction keeps its live entry. Tests: loaded states converge to the budget after closing documents and queries survive the unload/reload cycle; identical preambles keep sharing one loaded state; the store's eviction reporting is pinned drain-once at unit level.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (9)
📝 WalkthroughWalkthroughThe PR adds LRU tracking and budget enforcement for loaded preamble states, wires the budget to open sessions, and unloads excess states. CacheStore now reports evictions, allowing MasterServer to remove stale PCH metadata. Integration and unit tests cover release, sharing, and eviction draining. ChangesPreamble lifecycle management
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant MasterServer
participant Workspace
participant CacheStore
Client->>MasterServer: open or close document
MasterServer->>Workspace: update open-document budget
Workspace->>Workspace: touch and enforce loaded-state LRU
Workspace->>Workspace: unload excess PreambleState entries
MasterServer->>CacheStore: checkpoint and take evictions
CacheStore-->>MasterServer: evicted namespace/key records
MasterServer->>Workspace: erase missing PCH cache metadata
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Background
The PCH cache pairs each preamble with an index blob holding the preamble's symbols, links and inactive regions. The blob is memory-mapped on first use — and then retained for the server's lifetime: closing the document, going idle, even the store evicting the pair from disk, none of it releases the mapping. Every distinct preamble key ever touched keeps tens of MB mapped (the mappings are file-backed and reclaimable under pressure, but the address space and the working set grow without bound, and evicted blobs cannot even free their disk space while a mapping pins them).
Changes
open documents + 2(the count provider is wired by the master; the two slots of slack keep a just-closed state warm for a quick reopen and a shared key warm across consumer churn). Opening or rebuilding a state touches the LRU;didCloseshrinks the budget and enforces it. Unloading only drops the cache's reference — consumers holdshared_ptrcopies and finish safely — and the next use reopens the blob from disk lazily.Testing
tests/integration/server/test_memory_ownership.py): three documents with distinct preambles load three states and converge to the budget once all are closed (verified red before the fix — the count stayed at three forever); after the unload, reopening a file reloads the blob and queries keep working; four documents sharing one preamble keep sharing a single loaded state (regression guard).Notes
Summary by CodeRabbit
Bug Fixes
Tests