Skip to content

Commit b357d09

Browse files
authored
Merge pull request #1657 from atirna/fix/index-worker-explicit-memory-budget
fix(mem): honor explicit worker budget override
2 parents 105069b + 7f158e9 commit b357d09

3 files changed

Lines changed: 26 additions & 6 deletions

File tree

src/foundation/mem.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,19 @@ cbm_mem_budget_t cbm_mem_resolve_budget(size_t total_ram, double ram_fraction,
248248
cbm_mem_budget_t cbm_mem_resolve_budget_capped(size_t total_ram, double ram_fraction,
249249
const char *budget_mb, size_t hard_cap_bytes) {
250250
cbm_mem_budget_t result = cbm_mem_resolve_budget(total_ram, ram_fraction, budget_mb);
251+
/* The parent already divided the aggregate budget (env override or
252+
* ram_fraction) across job slots. That per-slot share is the hard cap:
253+
* N workers × a per-worker absolute override would oversubscribe the host
254+
* (#1654). A lower explicit value still wins. Keep CBM_MEM_BUDGET_MB as
255+
* the source when the env discriminator fired so the ceiling is visible
256+
* as the user's aggregate, not as a silent daemon_worker_cap rewrite. */
251257
if (hard_cap_bytes > 0 && (result.budget == 0 || result.budget > hard_cap_bytes)) {
258+
bool explicit_override =
259+
result.source != NULL && strcmp(result.source, "CBM_MEM_BUDGET_MB") == 0;
252260
result.budget = hard_cap_bytes;
253-
result.source = "daemon_worker_cap";
261+
if (!explicit_override) {
262+
result.source = "daemon_worker_cap";
263+
}
254264
result.hard_capped = true;
255265
}
256266
return result;

src/foundation/mem.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ void cbm_mem_init_with_cap(double ram_fraction, size_t hard_cap_bytes);
3131
* the caller never re-parses the env string. */
3232
typedef struct {
3333
size_t budget; /* resolved budget in bytes */
34-
const char *source; /* log token: "ram_fraction" | "CBM_MEM_BUDGET_MB" */
34+
const char *source; /* "ram_fraction" | "CBM_MEM_BUDGET_MB" | "daemon_worker_cap" */
3535
bool clamped; /* override was valid but exceeded total_ram → clamped down */
3636
bool invalid; /* override was present but unparseable / out-of-range / ≤0 */
3737
bool hard_capped; /* internal worker hard cap reduced the resolved budget */

tests/test_mem.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,11 @@ TEST(resolve_budget_override_when_total_unknown) {
516516
PASS();
517517
}
518518

519+
/* CBM_MEM_BUDGET_MB is an aggregate ceiling the parent divides across job
520+
* slots. A lower explicit value still wins; a raise is clipped to the per-slot
521+
* share so N workers cannot oversubscribe the host (#1654). The source stays
522+
* CBM_MEM_BUDGET_MB so the clip is the user's aggregate, not a silent
523+
* daemon_worker_cap rewrite of a fraction-derived default. */
519524
TEST(resolve_budget_worker_cap_preserves_lower_user_override) {
520525
size_t total = 8192 * CBM_TEST_MB;
521526
size_t worker_cap = 16 * CBM_TEST_MB;
@@ -524,10 +529,15 @@ TEST(resolve_budget_worker_cap_preserves_lower_user_override) {
524529
ASSERT_STR_EQ(lower.source, "CBM_MEM_BUDGET_MB");
525530
ASSERT_FALSE(lower.hard_capped);
526531

527-
cbm_mem_budget_t capped = cbm_mem_resolve_budget_capped(total, 0.5, "64", worker_cap);
528-
ASSERT_EQ(capped.budget, worker_cap);
529-
ASSERT_STR_EQ(capped.source, "daemon_worker_cap");
530-
ASSERT_TRUE(capped.hard_capped);
532+
cbm_mem_budget_t raised = cbm_mem_resolve_budget_capped(total, 0.5, "64", worker_cap);
533+
ASSERT_EQ(raised.budget, worker_cap);
534+
ASSERT_STR_EQ(raised.source, "CBM_MEM_BUDGET_MB");
535+
ASSERT_TRUE(raised.hard_capped);
536+
537+
cbm_mem_budget_t fraction = cbm_mem_resolve_budget_capped(total, 0.5, NULL, worker_cap);
538+
ASSERT_EQ(fraction.budget, worker_cap);
539+
ASSERT_STR_EQ(fraction.source, "daemon_worker_cap");
540+
ASSERT_TRUE(fraction.hard_capped);
531541
PASS();
532542
}
533543

0 commit comments

Comments
 (0)