Summary
Most of the daemon's live Rust heap has no resident owner, so the resident-memory authority charges a fraction of what it measures. Separately, the admission sample excludes swapped anonymous pages.
Evidence
Operator daemon, beta.59, 12:40 to 13:10 UTC, read-only. Sources: /proc/<pid>/smaps and tracedecay tool status --format json.
| Region |
Resident |
Swapped |
| mimalloc arenas (Rust heap) |
6.60 GiB |
3.64 GiB |
| glibc arena heaps (C libraries; fixed separately, see the linked PR) |
5.54 GiB |
3.76 GiB |
memory.retained_bytes (sum of charged owners): 3,550,304,770
memory.resident_bytes: 17,516,769,280
VmSwap: 8,387,836 kB. It is not counted in the admission sample (unreclaimable_bytes = RssAnon + RssShmem).
- 4 registered projects, 1 worktree each. No linked-worktree duplication.
Isolated reproduction. Debug production,hotpath build, MemoryMax=6G, MemorySwapMax=1G. Corpus: depth-1 clone of this repository (5,747 files). Cold index, then settle.
- Charged owners:
graph_catalog 400,257,698 plus graph_engine 665,139,632 (1,065,397,330 total).
- mimalloc arenas: 2,530 MiB resident plus 478 MiB swapped.
mi_collect(true) on all 113 threads (gdb, scratch daemon only) released nothing, so this is live or fragmented heap, not freed-but-retained pages.
- Symptom: every refresh after a commit is refused:
code-index worker resident-memory admission refused: ... observed_rss=3234574336 ... high_watermark=5798205849 requested=4429185024. The index stays warming indefinitely. That matches the operator's tracedecay project, which sat at rebuild_in_flight=true / code_graph_serving=pending for hours.
Expected
Retained Rust state that the daemon holds after a cold index (about 1.5 GB uncharged on this corpus) is registered as a resident owner, so it can be shed or at least attributed. Admission accounting also decides explicitly whether swapped anonymous pages count.
Not done
Attribution of the uncharged Rust heap. The Hotpath alloc lane reports allocated bytes per function, not live retention, so this needs a live-heap profile (for example dhat on a system-allocator build).
Summary
Most of the daemon's live Rust heap has no resident owner, so the resident-memory authority charges a fraction of what it measures. Separately, the admission sample excludes swapped anonymous pages.
Evidence
Operator daemon, beta.59, 12:40 to 13:10 UTC, read-only. Sources:
/proc/<pid>/smapsandtracedecay tool status --format json.memory.retained_bytes(sum of charged owners): 3,550,304,770memory.resident_bytes: 17,516,769,280VmSwap: 8,387,836 kB. It is not counted in the admission sample (unreclaimable_bytes=RssAnon + RssShmem).Isolated reproduction. Debug
production,hotpathbuild,MemoryMax=6G,MemorySwapMax=1G. Corpus: depth-1 clone of this repository (5,747 files). Cold index, then settle.graph_catalog400,257,698 plusgraph_engine665,139,632 (1,065,397,330 total).mi_collect(true)on all 113 threads (gdb, scratch daemon only) released nothing, so this is live or fragmented heap, not freed-but-retained pages.code-index worker resident-memory admission refused: ... observed_rss=3234574336 ... high_watermark=5798205849 requested=4429185024. The index stayswarmingindefinitely. That matches the operator's tracedecay project, which sat atrebuild_in_flight=true/code_graph_serving=pendingfor hours.Expected
Retained Rust state that the daemon holds after a cold index (about 1.5 GB uncharged on this corpus) is registered as a resident owner, so it can be shed or at least attributed. Admission accounting also decides explicitly whether swapped anonymous pages count.
Not done
Attribution of the uncharged Rust heap. The Hotpath alloc lane reports allocated bytes per function, not live retention, so this needs a live-heap profile (for example dhat on a system-allocator build).