Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/foundation/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
3 changes: 3 additions & 0 deletions src/foundation/mem.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#include <stdbool.h>
#include <stddef.h>

/* 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. */
Expand Down
10 changes: 3 additions & 7 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down
26 changes: 26 additions & 0 deletions tests/test_mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down
Loading