fix(mem): honor explicit worker budget override

Signed-off-by: Atirna <288419661+atirna@users.noreply.github.com>
This commit is contained in:
Atirna
2026-08-15 19:36:35 +05:30
parent 3162f09173
commit bf46b91f9a
2 changed files with 24 additions and 10 deletions
+13 -4
View File
@@ -248,10 +248,19 @@ cbm_mem_budget_t cbm_mem_resolve_budget(size_t total_ram, double ram_fraction,
cbm_mem_budget_t cbm_mem_resolve_budget_capped(size_t total_ram, double ram_fraction,
const char *budget_mb, size_t hard_cap_bytes) {
cbm_mem_budget_t result = cbm_mem_resolve_budget(total_ram, ram_fraction, budget_mb);
if (hard_cap_bytes > 0 && (result.budget == 0 || result.budget > hard_cap_bytes)) {
result.budget = hard_cap_bytes;
result.source = "daemon_worker_cap";
result.hard_capped = true;
/* CBM_MEM_BUDGET_MB is the user-facing emergency override for a single
* large index. Applying the daemon's equal-share cap after resolving it
* makes a requested raise indistinguishable from the default and leaves a
* worker stuck at a quarter of the host budget (#1654). The normal
* fraction-derived path remains capped, preserving aggregate admission for
* concurrent jobs; an explicit value remains clamped to detected RAM by
* cbm_mem_resolve_budget(). */
if (result.source == NULL || strcmp(result.source, "CBM_MEM_BUDGET_MB") != 0) {
if (hard_cap_bytes > 0 && (result.budget == 0 || result.budget > hard_cap_bytes)) {
result.budget = hard_cap_bytes;
result.source = "daemon_worker_cap";
result.hard_capped = true;
}
}
return result;
}
+11 -6
View File
@@ -490,7 +490,12 @@ TEST(resolve_budget_override_when_total_unknown) {
PASS();
}
TEST(resolve_budget_worker_cap_preserves_lower_user_override) {
/* A user who explicitly raises CBM_MEM_BUDGET_MB must not be silently reduced
* by the daemon's capacity slice. The parent-level slice still protects the
* default path, but the explicit override is the documented escape hatch for a
* single large index (#1654). Before the fix, a 64 MiB request was reported as
* daemon_worker_cap at 16 MiB instead of honoring the requested 64 MiB. */
TEST(resolve_budget_worker_cap_honors_explicit_override) {
size_t total = 8192 * CBM_TEST_MB;
size_t worker_cap = 16 * CBM_TEST_MB;
cbm_mem_budget_t lower = cbm_mem_resolve_budget_capped(total, 0.5, "8", worker_cap);
@@ -498,10 +503,10 @@ TEST(resolve_budget_worker_cap_preserves_lower_user_override) {
ASSERT_STR_EQ(lower.source, "CBM_MEM_BUDGET_MB");
ASSERT_FALSE(lower.hard_capped);
cbm_mem_budget_t capped = cbm_mem_resolve_budget_capped(total, 0.5, "64", worker_cap);
ASSERT_EQ(capped.budget, worker_cap);
ASSERT_STR_EQ(capped.source, "daemon_worker_cap");
ASSERT_TRUE(capped.hard_capped);
cbm_mem_budget_t raised = cbm_mem_resolve_budget_capped(total, 0.5, "64", worker_cap);
ASSERT_EQ(raised.budget, 64 * CBM_TEST_MB);
ASSERT_STR_EQ(raised.source, "CBM_MEM_BUDGET_MB");
ASSERT_FALSE(raised.hard_capped);
PASS();
}
@@ -1288,7 +1293,7 @@ SUITE(mem) {
RUN_TEST(resolve_budget_override_wins);
RUN_TEST(resolve_budget_override_clamped_to_total);
RUN_TEST(resolve_budget_override_when_total_unknown);
RUN_TEST(resolve_budget_worker_cap_preserves_lower_user_override);
RUN_TEST(resolve_budget_worker_cap_honors_explicit_override);
RUN_TEST(resolve_budget_invalid_override_falls_back);
RUN_TEST(resolve_budget_override_overflow_clamps_to_total);
RUN_TEST(resolve_budget_override_overflow_total_unknown_caps);