Repository navigation
perf(cli): allocate through mimalloc in the musl release builds - #310
Conversation
musl's allocator serializes threads, so the static Linux release binaries got slower as threads were added: a full index of this repository took 129 s at 32 threads against 50 s at one, where a glibc build takes 5 s. Use mimalloc (v2, MIT) as the global allocator on musl targets only. The dependency is target-gated, so glibc, macOS and Windows builds keep their system allocator and their dependency graph is unchanged. Measured with the release toolchain (cargo-zigbuild 0.23.0, zig 0.15.1, rustc 1.98.0) on the same archive: 32 threads 129 s -> 8.2-8.4 s over three runs, 4 threads 70 s -> 13 s, 1 thread 50 s -> 36 s. Peak RSS at 32 threads rises from 249 MB to about 500 MB. Nodes, edges, unresolved refs and file rows are identical to 0.53.1's.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9bbf9be071
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| /// slower as threads were added: a full index of this repository took over two | ||
| /// minutes at 32 threads, against 51 s at one. Through mimalloc it takes 8 s. |
There was a problem hiding this comment.
Remove unreproducible benchmark timings
These hard-coded timings publish a performance claim without an in-repository record of the commit, corpus, environment, exact command, run count, and dispersion, so the numbers will become misleading as the repository and hardware change. Keep the allocator rationale here and move the measurements to reproducible benchmark evidence.
AGENTS.md reference: AGENTS.md:L141-L142
Useful? React with 👍 / 👎.
Codecov Report✅ All modified and coverable lines are covered by tests. @@ Coverage Diff @@
## main #310 +/- ##
==========================================
- Coverage 95.07% 95.07% -0.01%
==========================================
Files 198 198
Lines 108998 108998
==========================================
- Hits 103632 103630 -2
- Misses 5366 5368 +2
🚀 New features to boost your workflow:
|
The release record for #310: the release PR merge and its tag SHA, the workflow run, the published digest, and the black-box acceptance against v0.53.1, plus a dated entry for the change itself with its measurement method. Current alignment lists v0.53.2.
Summary
The Linux release archives are static musl builds, and musl's allocator serializes threads. Indexing therefore got slower as threads were added: a full index of this repository took 122 s at 32 threads against 51 s at one, where a glibc build takes 5 s.
This PR makes mimalloc the global allocator on musl targets only:
crates/codegraph-cli/Cargo.toml:mimalloc = { version = "0.1.52", default-features = false, features = ["v2"] }under[target.'cfg(target_env = "musl")'.dependencies].mimallocand its bundled C library (libmimalloc-sys0.1.49, mimalloc 2.3.2) are MIT;ccwas already in the graph.crates/codegraph-cli/src/main.rs: a#[cfg(target_env = "musl")] #[global_allocator]static. It is the only code change. The daemon is the same binary.Cargo.lock: the two new crates.README.mdanddocs/readme/README.zh-CN.md: one matching sentence in the prebuilt-archives sections.glibc, macOS and Windows builds keep their system allocator, and their dependency graph is unchanged. There is no extraction-version bump and no golden change.
Why v2 and not v3. mimalloc v3's defaults hold memory longer: peak RSS was 750 MB at 32 threads. Getting it down needs
MIMALLOC_PURGE_DELAYat runtime plus a compile-time arena setting. v2's defaults purge freed pages after 10 ms (decommitting withMADV_DONTNEED), so a long-livedserve --mcpprocess should hand an indexing burst back. That last point follows from the documented defaults and was not measured here.The design passed the kirocodex plan gate in round 2 (1 → 0). Round 1's only item was keeping the Chinese README mirror in sync.
Measurements
Full index of an archive of
d26df90(689 files, viewer bundle excluded) on a 32-core machine. Wall time / peak RSS, from/usr/bin/time:RAYON_NUM_THREADSVerification
cargo zigbuild --locked --release -p codegraph-rs --target <t>):x86_64-unknown-linux-musl: built and statically linked;aarch64-unknown-linux-musl: built and statically linked. It was not run, because this host has no qemu.cargo clippy --locked --target x86_64-unknown-linux-musl -p codegraph-rs -- -D warningsis clean, so the musl-only code is checked too.make pre-cion this tree at rustc 1.98 passed: 4,360 Rust tests and 569 frontend tests.cargo audit: no vulnerabilities. The 452-crate scan runs locally, but its yank checks fail on the local registry mirror. CI's Security Audit job, the authoritative run, passed.The Release workflow's two musl jobs build this for real. A failed build leaves the draft unpublished.
Not in this PR
🤖 Generated with Claude Code