perf: use mimalloc as the global allocator in the binary - #137
Open
BenjaminDEMAILLE wants to merge 1 commit into
Open
perf: use mimalloc as the global allocator in the binary#137BenjaminDEMAILLE wants to merge 1 commit into
BenjaminDEMAILLE wants to merge 1 commit into
Conversation
The RNA-Seq pipeline is allocation-heavy (per-read buffers, mate-pair maps, per-chromosome vectors that grow during counting) and performs those allocations from several rayon worker threads concurrently, so it is sensitive to allocator lock contention. mimalloc uses per-thread free lists and avoids most of that contention. Measured on a synthetic 4M-read coordinate-sorted BAM (24 contigs) with a 1.2M-line GTF (60k genes), aarch64 macOS, --threads 4, 5 runs: before: 22.122 s ± 0.197 s (user 22.567 s) after: 20.540 s ± 0.223 s (user 19.105 s) That is 1.08x wall clock and a 15% drop in user CPU time. All data outputs (featureCounts TSV, TIN, preseq, samtools stats, Qualimap, RSeQC) are byte-identical before and after. The allocator is declared in src/main.rs rather than src/lib.rs on purpose: `#[global_allocator]` is process-wide, so the library must not impose one on its dependents. It sits behind a default-on `mimalloc` feature so it can be disabled with --no-default-features, e.g. when profiling with an external heap profiler. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
BenjaminDEMAILLE
force-pushed
the
perf/mimalloc-allocator
branch
from
August 13, 2026 23:44
cd857ad to
e2fdcb6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Uses mimalloc as the
#[global_allocator]for therustqcbinary, behind a default-onmimallocfeature.Why
The single-pass pipeline allocates constantly (per-read buffers, the mate-pair
HashMap, per-chromosome vectors that grow during counting) and does so from several rayon workers at once. That pattern is dominated by allocator lock contention under the system allocator.Measurement
Synthetic dataset (a real one would be better, happy to re-run against the RustQC-benchmarks pipeline):
--threads 4,hyperfine -w 1 -r 5main1.08 ± 0.02x faster, and user CPU time drops 15%. The gap should widen with higher
--threadssince the win is contention-related.Confirmed on a second dataset (same size but with random read sequences, so the dedup maps are fully populated), 5 interleaved runs, medians:
mainSame shape: 1.06x wall clock, user CPU down 16%.
Parity
All data outputs are byte-identical before/after:
featureCounts.tsv,tin.xls,lc_extrap.txt, samtoolsstats/flagstat/idxstats, Qualimap, and all RSeQC outputs.cargo test --releasepasses (200 + 12 + 18 + 2).Notes / trade-offs
src/main.rs, notsrc/lib.rs.#[global_allocator]is process-wide, so a library must not impose one on its dependents. Library users who want it can declare it themselves.--no-default-featuresrestores the system allocator, which is what you want when profiling with an external heap profiler.cc, so no new system requirement beyond the toolchainrust-htslibalready needs. It cross-compiles to all 8 release targets (linux gnu / darwin, x86_64 / aarch64).Unrelated observation
While diffing outputs I noticed
dupradar/*_duprateExpDens.{svg,png}is not reproducible run-to-run onmainalone: the same points are emitted in a different order between two runs of the same binary on the same input. Data outputs are all stable; it looks like plot points are iterated straight out of aHashMap. Happy to open a separate issue.🤖 Generated with Claude Code
Part of #143.