diff --git a/src/foundation/mem.c b/src/foundation/mem.c index 67ef4d14e..b0a79f6c2 100644 --- a/src/foundation/mem.c +++ b/src/foundation/mem.c @@ -106,6 +106,21 @@ static void check_pressure(size_t rss) { /* ── Public API ────────────────────────────────────────────────── */ +#define RAM_FRACTION_DEFAULT 0.5 +#define RAM_FRACTION_16GB 0.25 +#define RAM_FRACTION_32GB 0.35 +#define RAM_BYTES_PER_GB (1024ULL * 1024 * 1024) + +double cbm_mem_ram_fraction_for_total(size_t total_ram_bytes) { + if (total_ram_bytes <= 16ULL * RAM_BYTES_PER_GB) { + return RAM_FRACTION_16GB; + } + if (total_ram_bytes <= 32ULL * RAM_BYTES_PER_GB) { + return RAM_FRACTION_32GB; + } + return RAM_FRACTION_DEFAULT; +} + void cbm_mem_init(double ram_fraction) { int expected = 0; if (!atomic_compare_exchange_strong(&g_initialized, &expected, 1)) { diff --git a/src/foundation/mem.h b/src/foundation/mem.h index 5001410a8..8c23c508a 100644 --- a/src/foundation/mem.h +++ b/src/foundation/mem.h @@ -11,6 +11,9 @@ #include #include +/* Tiered default fraction for MCP startup: 25% on <=16GB, 35% on <=32GB, else 50%. */ +double cbm_mem_ram_fraction_for_total(size_t total_ram_bytes); + /* Initialize memory budget = ram_fraction * total_physical_ram. * Thread-safe: only the first call takes effect. * Configures mimalloc options for reduced upfront memory. */ diff --git a/src/main.c b/src/main.c index f2b72cba8..66cfb3430 100644 --- a/src/main.c +++ b/src/main.c @@ -30,8 +30,6 @@ enum { MAIN_MAX_PORT = 65536, PARENT_WATCHDOG_STACK_SIZE = 64 * CBM_SZ_1K, /* watchdog only polls — tiny stack suffices */ }; -#define MAIN_RAM_FRACTION 0.5 - #define SLEN(s) (sizeof(s) - 1) #include "foundation/log.h" #include "foundation/diagnostics.h" @@ -324,11 +322,11 @@ static int handle_subcommand(int argc, char **argv) { return 0; } if (strcmp(argv[i], "cli") == 0) { - cbm_mem_init(MAIN_RAM_FRACTION); + cbm_mem_init(cbm_mem_ram_fraction_for_total(cbm_system_info().total_ram)); return run_cli(argc - i - SKIP_ONE, argv + i + SKIP_ONE); } if (strcmp(argv[i], "hook-augment") == 0) { - cbm_mem_init(MAIN_RAM_FRACTION); + cbm_mem_init(cbm_mem_ram_fraction_for_total(cbm_system_info().total_ram)); return cbm_cmd_hook_augment(); } if (strcmp(argv[i], "install") == 0) { @@ -424,9 +422,7 @@ int main(int argc, char **argv) { #endif /* Default: MCP server on stdio */ - cbm_mem_init(MAIN_RAM_FRACTION); /* 50% of RAM — safe now because mimalloc tracks ALL - * memory (C + C++ allocations) via global override. - * No more untracked heap blind spots. */ + cbm_mem_init(cbm_mem_ram_fraction_for_total(cbm_system_info().total_ram)); /* Store binary path for subprocess spawning + hook log sink */ cbm_http_server_set_binary_path(argv[0]); cbm_log_set_sink(cbm_ui_log_append); diff --git a/tests/test_mem.c b/tests/test_mem.c index debb9b505..3130fbecf 100644 --- a/tests/test_mem.c +++ b/tests/test_mem.c @@ -140,6 +140,29 @@ TEST(mem_over_budget_low_rss) { PASS(); } +/* ── Tiered RAM fraction (host-size defaults) ─────────────────── */ + +TEST(mem_ram_fraction_16gb_tier) { + size_t ram_16gb = 16ULL * 1024 * 1024 * 1024; + ASSERT_EQ(cbm_mem_ram_fraction_for_total(ram_16gb), 0.25); + ASSERT_EQ(cbm_mem_ram_fraction_for_total(ram_16gb - 1), 0.25); + PASS(); +} + +TEST(mem_ram_fraction_32gb_tier) { + size_t ram_32gb = 32ULL * 1024 * 1024 * 1024; + size_t ram_17gb = 17ULL * 1024 * 1024 * 1024; + ASSERT_EQ(cbm_mem_ram_fraction_for_total(ram_17gb), 0.35); + ASSERT_EQ(cbm_mem_ram_fraction_for_total(ram_32gb), 0.35); + PASS(); +} + +TEST(mem_ram_fraction_large_host) { + size_t ram_64gb = 64ULL * 1024 * 1024 * 1024; + ASSERT_EQ(cbm_mem_ram_fraction_for_total(ram_64gb), 0.5); + PASS(); +} + /* ── RSS tracking tests ───────────────────────────────────────── */ TEST(mem_rss_positive) { @@ -638,6 +661,9 @@ SUITE(mem) { RUN_TEST(mem_worker_budget_one_worker); RUN_TEST(mem_worker_budget_many_workers); RUN_TEST(mem_over_budget_low_rss); + RUN_TEST(mem_ram_fraction_16gb_tier); + RUN_TEST(mem_ram_fraction_32gb_tier); + RUN_TEST(mem_ram_fraction_large_host); /* RSS tracking */ RUN_TEST(mem_rss_positive); RUN_TEST(mem_peak_rss_gte_rss);