mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-04 10:48:20 +00:00
perf(index): run supervised index workers at below-normal CPU priority
A full index saturates every core in the parallel extraction pass, and interactive CLI/MCP queries (CPU-bound at start-up) were measured taking twice their wall time behind it with flat CPU time: pure run-queue contention. The index-worker role now lowers its own priority once, before any indexing thread is created: nice 10 on POSIX, BELOW_NORMAL_PRIORITY_CLASS on Windows. It never raises priority: a process already nicer than 10 (or in the IDLE / BELOW_NORMAL class) is left alone. Plain nice only, not macOS background QoS, which would pin indexing to efficiency cores and throttle its I/O. Failure is logged and ignored. The test runs the helper in a forked child and checks both legs: a normal-priority child ends at nice >= 10, and a child started nicer than that is left where it was. Refs #2834 Signed-off-by: Shane McCarron <shane.mccarron@corvexconnect.com>
This commit is contained in:
1 parent
a3831c9795
commit
349d80c643
4 files changed
+91
No files matched your search
@@ -729,3 +729,28 @@ const char *cbm_resolve_cache_dir(void) {
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* ── CPU scheduling priority ────────────────── */
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
bool cbm_lower_cpu_priority(void) {
|
||||
#ifdef _WIN32
|
||||
HANDLE self = GetCurrentProcess();
|
||||
DWORD current = GetPriorityClass(self);
|
||||
if (current == IDLE_PRIORITY_CLASS || current == BELOW_NORMAL_PRIORITY_CLASS) {
|
||||
return true; /* already at least this low: never raise priority */
|
||||
}
|
||||
return SetPriorityClass(self, BELOW_NORMAL_PRIORITY_CLASS) != 0;
|
||||
#else
|
||||
/* getpriority can legitimately return -1, so errno is the only error signal. */
|
||||
errno = 0;
|
||||
int current = getpriority(PRIO_PROCESS, 0);
|
||||
if (errno == 0 && current >= CBM_LOW_CPU_PRIORITY_NICE) {
|
||||
return true; /* already at least this nice: never raise priority */
|
||||
}
|
||||
return setpriority(PRIO_PROCESS, 0, CBM_LOW_CPU_PRIORITY_NICE) == 0;
|
||||
#endif
|
||||
}
|
||||
@@ -215,4 +215,17 @@ int64_t cbm_file_size(const char *path);
|
||||
* On POSIX, this is a no-op. Returns the input pointer. */
|
||||
char *cbm_normalize_path_sep(char *path);
|
||||
|
||||
/* ── CPU scheduling priority ───────────────────────────────────── */
|
||||
|
||||
enum { CBM_LOW_CPU_PRIORITY_NICE = 10 };
|
||||
|
||||
/* Lower this process's CPU scheduling priority so background work yields the
|
||||
* cores to interactive processes. POSIX: nice CBM_LOW_CPU_PRIORITY_NICE (never
|
||||
* raises an already-nicer process). Plain nice only, deliberately not macOS
|
||||
* background QoS: that pins work to efficiency cores and throttles I/O.
|
||||
* Windows: BELOW_NORMAL_PRIORITY_CLASS. On Linux nice is per thread, so call
|
||||
* this before creating threads; later threads inherit it.
|
||||
* Returns false when the priority could not be changed. */
|
||||
bool cbm_lower_cpu_priority(void);
|
||||
|
||||
#endif /* CBM_PLATFORM_H */
|
||||
@@ -902,6 +902,12 @@ static int run_cli(int argc, char **argv, cbm_project_lock_manager_t *project_lo
|
||||
* own here, and only here (cbm_sqlite_dedicated_heap). */
|
||||
cbm_sqlite_dedicated_heap(true);
|
||||
cbm_memev_process_role("worker");
|
||||
/* A full index saturates every core; run it below normal priority so
|
||||
* interactive CLI/MCP queries are not starved. Before any indexing
|
||||
* thread exists, so they all inherit it. Failure is harmless. */
|
||||
if (!cbm_lower_cpu_priority()) {
|
||||
cbm_log_info("index.worker.priority", "lowered", "false");
|
||||
}
|
||||
}
|
||||
cbm_index_set_worker_role_options(index_worker, response_out, worker_single_thread,
|
||||
worker_marker, worker_quarantine,
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
#include <unistd.h>
|
||||
#ifndef _WIN32
|
||||
#include <sys/stat.h> /* chmod for the symlink-policy mode legs */
|
||||
#include <errno.h>
|
||||
#include <sys/resource.h> /* getpriority for the worker-priority leg */
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -1442,6 +1445,49 @@ TEST(regex_estimate_counts_brackets_and_escapes_literally) {
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* An index worker lowers its own priority (#2834). A non-root process cannot
|
||||
* raise it back, so the helper runs in a forked child that reports its nice. */
|
||||
TEST(platform_lower_cpu_priority_nices_the_process) {
|
||||
#ifdef _WIN32
|
||||
SKIP_PLATFORM("POSIX nice contract");
|
||||
#else
|
||||
int fds[2];
|
||||
ASSERT_EQ(pipe(fds), 0);
|
||||
pid_t child = fork();
|
||||
if (child == 0) {
|
||||
(void)close(fds[0]);
|
||||
/* report: lowered ok, nice after; then, from a nicer start, ok, target, nice after */
|
||||
int report[5] = {cbm_lower_cpu_priority() ? 1 : 0, 0, 0, 0, 0};
|
||||
errno = 0;
|
||||
report[1] = getpriority(PRIO_PROCESS, 0);
|
||||
if (errno != 0) {
|
||||
report[0] = 0;
|
||||
}
|
||||
/* Never-raise leg: start nicer than the helper's level; it must leave it. */
|
||||
report[3] = report[1] >= 15 ? 19 : 15;
|
||||
if (setpriority(PRIO_PROCESS, 0, report[3]) == 0) {
|
||||
report[2] = cbm_lower_cpu_priority() ? 1 : 0;
|
||||
errno = 0;
|
||||
report[4] = getpriority(PRIO_PROCESS, 0);
|
||||
}
|
||||
_exit(write(fds[1], report, sizeof(report)) == (ssize_t)sizeof(report) ? 0 : 1);
|
||||
}
|
||||
ASSERT_TRUE(child > 0);
|
||||
(void)close(fds[1]);
|
||||
int report[5] = {0, 0, 0, 0, 0};
|
||||
ssize_t got = read(fds[0], report, sizeof(report));
|
||||
(void)close(fds[0]);
|
||||
int status = 0;
|
||||
(void)waitpid(child, &status, 0);
|
||||
ASSERT_EQ(got, (ssize_t)sizeof(report));
|
||||
ASSERT_EQ(report[0], 1);
|
||||
ASSERT_TRUE(report[1] >= CBM_LOW_CPU_PRIORITY_NICE);
|
||||
ASSERT_EQ(report[2], 1);
|
||||
ASSERT_EQ(report[4], report[3]);
|
||||
PASS();
|
||||
#endif
|
||||
}
|
||||
|
||||
SUITE(platform) {
|
||||
RUN_TEST(platform_file_apis_survive_max_path_overflow);
|
||||
RUN_TEST(platform_mkdir_p_follows_own_symlink_only_when_opted_in);
|
||||
@@ -1477,6 +1523,7 @@ SUITE(platform) {
|
||||
RUN_TEST(platform_env_long_refuses_what_it_cannot_read);
|
||||
RUN_TEST(platform_env_dup_honours_the_settings_resolver);
|
||||
RUN_TEST(platform_system_info);
|
||||
RUN_TEST(platform_lower_cpu_priority_nices_the_process);
|
||||
RUN_TEST(regex_compile_refuses_oversized_expansion);
|
||||
RUN_TEST(regex_compile_accepts_expansion_under_budget);
|
||||
RUN_TEST(regex_compile_refuses_overlong_pattern);
|
||||
|
||||
Reference in new issue
Block a user