feat(mem): CBM_MAX_MEMORY_MB explicit memory-budget override (#580)#586
feat(mem): CBM_MAX_MEMORY_MB explicit memory-budget override (#580)#586yangsec888 wants to merge 1 commit into
Conversation
Add a CBM_MAX_MEMORY_MB env var that overrides the ram_fraction × total_RAM budget with an explicit cap in MiB. Lets RAM-constrained hosts (no cgroup) cap the in-memory graph, and lets containers pin a budget below the cgroup limit so headroom is left for sibling processes. Same precedence as CBM_WORKERS: explicit override > implicit detection. Budget math is extracted into a pure, testable cbm_mem_resolve_budget() since cbm_mem_init is one-shot per process. Logs source=env|ram_fraction on mem.init and warns on invalid/clamped values. Closes DeusData#580. Signed-off-by: Sam Li <yangsec888@gmail.com>
|
Huge thanks for opening this PR and for the work you put into it. The maintainer shop is currently full, so this may sit for a bit before it gets a proper review. We will come back to this as soon as possible with real feedback; I wanted to make sure it did not sit unacknowledged in the meantime. |
|
Quick status note: this PR is one of four open memory/RAM-policy changes (#833, #752, #586, #685) that we've reviewed individually and found genuinely complementary — so rather than merging them piecemeal, we're doing a combined design pass over the whole memory policy (explicit override, host-tiered defaults, retention bounds, post-index release, and the Windows auto-sync driver in #841) and will respond here with a concrete direction shortly. Your work is very much part of that plan — thanks for your patience! |
|
Thank you for this — the engineering was genuinely good (a pure, testable budget resolver with clamp-to-total-RAM and source logging). The reason we're closing it: main already has an equivalent explicit override, CBM_MEM_BUDGET_MB (checked first in cbm_mem_init, before any RAM-fraction logic, so it wins over the tiered default). Adding CBM_MAX_MEMORY_MB alongside it would give two env vars for one purpose with subtly different clamp semantics. If you'd like, your clamp + |
Summary
Adds a
CBM_MAX_MEMORY_MBenv var that overrides theram_fraction × total_RAMmemory budget with an explicit cap in MiB. Closes the--max-memoryrequest in #580 and gives #563 a workaround on hosts without cgroup limits (macOS / bare metal).Motivation
The knowledge graph is built fully in memory and the budget is sized to 50% of detected RAM. Two gaps remain even after cgroup-aware detection landed:
0.5 × cgroupcan still be too high. There was no way to pin a lower, explicit budget.CBM_MAX_MEMORY_MBlets the operator set the in-memory budget directly, with the same precedence shape as the existingCBM_WORKERSoverride: explicit override > implicit detection.Changes
src/foundation/mem.ccbm_mem_resolve_budget(total_ram, ram_fraction, max_memory_mb)— single source of truth for the budget number (no globals/env), testable.cbm_mem_initreadsCBM_MAX_MEMORY_MBviacbm_safe_getenv, applies it, logssource=env|ram_fractionon themem.initline, and warns onmem.max.invalid(non-numeric/≤0) /mem.max.clamped(above total RAM).src/foundation/mem.h— declarecbm_mem_resolve_budget; document the env var.README.md— addCBM_MAX_MEMORY_MBto the env-var table.tests/test_mem.c— 6 cases over the pure resolver.Semantics
CBM_MAX_MEMORY_MBram_fraction × total_ram(unchanged default)total_ram(+mem.max.clampedwarn)0, negative, non-numericmem.max.invalidwarn)mem.initnow logs the chosen source, e.g.:Design notes
total_ramwhen known so it can never claim more than physical/cgroup RAM, but is honored as-is when detection returns 0 (so it also rescues hosts where RAM detection fails).cbm_mem_initis one-shot per process (atomic CAS) and can't be re-exercised in-process.Testing
tests/test_mem.cresolver cases.cbm_mem_resolve_budget(12/12 checks pass).clang-format --dry-run --Werrorclean on all changed files.CBM_MAX_MEMORY_MB=512 codebase-memory-mcp …→mem.init … source=env.