Skip to content

perf(cli): every one-shot cli call hashes the whole executable; under a concurrent index this dominates query latency #2834

Open

Description

@halindrome

Summary

Each codebase-memory-mcp cli <tool> process computes a SHA-256 of its own executable image before it contacts the daemon. For a ~300 MB binary that is the entire client-side cost of a query, and because it is CPU-bound it is the first thing starved when an index worker is saturating the cores. Hook/agent wrappers that run one cli process per query pay it on every call.

Where

  • src/main.c:3100 — main() → main_build_identity (the later call at main.c:1894 in main_local_cli_daemon_execute reuses the cached result)
  • src/mcp/index_supervisor.c:119-147 — cbm_index_supervisor_capture_build_fingerprint (its own comment at :125: "computing the real fingerprint hashes the ENTIRE executable image")
  • src/daemon/runtime.c:1009 → runtime_process_image_reference_acquire → cbm_daemon_build_fingerprint_native_file (POSIX: src/daemon/service.c:358, SHA-256 loop over the image at :383)

Confirmed with lldb attached mid-run to an idle cli search_graph: the main thread is in sha256_transform ← cbm_daemon_build_fingerprint_native_file ← main_build_identity ← main at 0.8 s and 1.1 s into a 1.45 s call.

Measurements (Apple Silicon, 10 cores, 300 MB binary)

time
cli search_graph idle, build before #2441 1.45 s real / 1.2 s user
SHA-256 of the binary, sha256.c before #2441 1.18 s
SHA-256 of the binary, sha256.c on main (ARMv8 SHA2, #2441) 0.115 s
8 parallel cli search_graph, idle median 1.95 s
8 parallel cli search_graph, during a full index of a 64k-node repo median 3.7 s (user CPU per call unchanged at ~1.7 s)

Per-call user CPU stays flat under load while wall time doubles, and querying the project being indexed vs. a different project makes no difference — i.e. this is CPU contention, not a lock. #2441 already cuts the hash ~10x on hardware with SHA extensions, but the cost is still O(binary size) per call and is paid in full on CPUs without them.

Field report this came from: on a ~100k-node monorepo, one-shot wrapper queries took 3–36 s (median ~13 s) during a session where the watcher was re-indexing almost continuously. The repro above confirms the mechanism but only reaches ~2x at 64k nodes; the extra amplification in the field (longer index runs, more concurrent agents, possible memory pressure) is not yet measured.

Proposed fix

A PR will follow for the contention half: run supervised index workers at background CPU priority, so interactive clients (and the user's editor/shell) win the CPU during long index runs. Nothing in src/ lowers worker priority today.

The per-call hash is already ~10x cheaper on hardware with SHA extensions after #2441. Removing it entirely touches cohort identity, so these options are left for maintainer input rather than included in the PR:

  1. Use the linker's build identity (Mach-O LC_UUID, ELF NT_GNU_BUILD_ID, PE debug GUID) as the client-side cohort fingerprint — O(1), no cache file. Keep full-image hashing for the daemon-side peer checks (runtime_activation_peer_matches_claim, status/stop paths), so activation trust is unchanged.
  2. Or cache the fingerprint in the cache dir keyed by the image's (dev, inode, size, mtime_ns, ctime_ns); recompute only on a key miss.

Investigated and written by Claude Opus 5.5 (Anthropic) in Claude Code, at the request of @halindrome.

Activity

  1. added
    editor/integrationEditor compatibility and CLI integration
    parsing/qualityGraph extraction bugs, false positives, missing edges
    ux/behaviorDisplay bugs, docs, adoption UX
    on Oct 29, 2026
  2. DeusData commented on Nov 2, 2026

    @DeusData
    Owner

    The index-worker priority part of this landed on main in 7a9b1cb (#2838, thanks to @halindrome): supervised index workers now run at below-normal CPU priority. This issue stays open for the per-call executable-hash cost, which is a separate piece of work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    editor/integrationEditor compatibility and CLI integrationparsing/qualityGraph extraction bugs, false positives, missing edgesux/behaviorDisplay bugs, docs, adoption UX

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions