feat(platform): CBM_WORKERS env override for cbm_default_worker_count

Adds a CBM_WORKERS env knob (clamped to [1, 256], invalid values warned
and ignored) that explicitly sets the parallel-indexing worker count.
In containers, sysconf(_SC_NPROCESSORS_ONLN) reports host CPUs rather
than the cgroup's effective quota, so a 1-vCPU pod on a 16-core node
otherwise spawns ~16 workers — the dominant OOMKill driver. When unset,
behaviour is unchanged.

From #364.
This commit is contained in:
yangsec888 authored and Martin Vogel committed 2026-05-30 17:32:47 +02:00
1 parent d895c16553
commit d95223817e
3 files changed
+73 -1

No files matched your search

+1
View File
@@ -433,6 +433,7 @@ codebase-memory-mcp config reset auto_index # reset to default
| `CBM_CACHE_DIR` | `~/.cache/codebase-memory-mcp` | Override the database storage directory. All project indexes and config are stored here. |
| `CBM_DIAGNOSTICS` | `false` | Set to `1` or `true` to enable periodic diagnostics output to `/tmp/cbm-diagnostics-<pid>.json`. |
| `CBM_DOWNLOAD_URL` | *(GitHub releases)* | Override the download URL for updates. Used for testing or self-hosted deployments. |
| `CBM_WORKERS` | *(detected)* | Override the parallel-indexing worker count returned by `cbm_default_worker_count`. Useful inside containers where `sysconf(_SC_NPROCESSORS_ONLN)` reports host CPUs rather than the cgroup's effective quota. Range 1–256; invalid values are ignored with a warning. |
```bash
# Store indexes in a custom directory
+17 -1
View File
@@ -10,9 +10,11 @@
*/
#include "foundation/constants.h"
enum { DEFAULT_CORES = 1, MIN_WORKERS = 1 };
enum { DEFAULT_CORES = 1, MIN_WORKERS = 1, CBM_WORKERS_MAX = 256 };
#include "foundation/log.h"
#include "foundation/platform.h"
#include <stdint.h> // uint64_t
#include <stdlib.h> // strtol
#include <string.h>
#ifdef _WIN32
@@ -168,6 +170,20 @@ cbm_system_info_t cbm_system_info(void) {
}
int cbm_default_worker_count(bool initial) {
/* CBM_WORKERS env override (clamped to [1, CBM_WORKERS_MAX]).
* Useful inside containers where sysconf(_SC_NPROCESSORS_ONLN)
* reports host CPUs rather than the cgroup's effective CPU quota.
* Same precedence shape as other CBM_* env overrides:
* explicit override > implicit detection. */
char buf[CBM_SZ_32];
if (cbm_safe_getenv("CBM_WORKERS", buf, sizeof(buf), NULL) != NULL) {
long n = strtol(buf, NULL, CBM_DECIMAL_BASE);
if (n >= MIN_WORKERS && n <= CBM_WORKERS_MAX) {
return (int)n;
}
cbm_log_warn("workers.env.invalid", "value", buf, "fallback", "sysconf");
}
cbm_system_info_t info = cbm_system_info();
if (initial) {
/* Use all cores for initial indexing — user is waiting */
+55
View File
@@ -3,6 +3,7 @@
*/
#include "test_framework.h"
#include "../src/foundation/platform.h"
#include <stdlib.h> /* setenv, unsetenv */
#include <unistd.h>
TEST(platform_now_ns) {
@@ -68,6 +69,57 @@ TEST(platform_mmap_nonexistent) {
PASS();
}
/*
* CBM_WORKERS env override for cbm_default_worker_count.
*
* Containers running cbm on a host with more CPUs than the cgroup's
* effective quota currently see ~host_cpu workers spawned because
* sysconf(_SC_NPROCESSORS_ONLN) is not cgroup-aware (see GitHub
* issue for the cgroup-detection ask). CBM_WORKERS is the smaller,
* explicit-override path that ships independently.
*/
TEST(platform_default_workers_env_override) {
setenv("CBM_WORKERS", "4", 1);
int n = cbm_default_worker_count(true);
ASSERT_EQ(n, 4);
/* initial=false should also honor the explicit override. */
int m = cbm_default_worker_count(false);
ASSERT_EQ(m, 4);
unsetenv("CBM_WORKERS");
PASS();
}
TEST(platform_default_workers_env_invalid) {
/* Out-of-range values (< 1 or > 256) and non-numeric strings
* fall back to the sysconf-derived default. */
int baseline = cbm_default_worker_count(true);
ASSERT_GT(baseline, 0);
setenv("CBM_WORKERS", "0", 1);
ASSERT_EQ(cbm_default_worker_count(true), baseline);
setenv("CBM_WORKERS", "-1", 1);
ASSERT_EQ(cbm_default_worker_count(true), baseline);
setenv("CBM_WORKERS", "9999", 1);
ASSERT_EQ(cbm_default_worker_count(true), baseline);
setenv("CBM_WORKERS", "not-a-number", 1);
ASSERT_EQ(cbm_default_worker_count(true), baseline);
unsetenv("CBM_WORKERS");
PASS();
}
TEST(platform_default_workers_env_unset) {
/* When CBM_WORKERS is unset the result matches today's behaviour
* (info.total_cores for initial=true, perf_cores-1 for false). */
unsetenv("CBM_WORKERS");
cbm_system_info_t info = cbm_system_info();
ASSERT_EQ(cbm_default_worker_count(true), info.total_cores);
PASS();
}
SUITE(platform) {
RUN_TEST(platform_now_ns);
RUN_TEST(platform_now_ms);
@@ -77,4 +129,7 @@ SUITE(platform) {
RUN_TEST(platform_file_size);
RUN_TEST(platform_mmap);
RUN_TEST(platform_mmap_nonexistent);
RUN_TEST(platform_default_workers_env_override);
RUN_TEST(platform_default_workers_env_invalid);
RUN_TEST(platform_default_workers_env_unset);
}