Skip to content

Add optional mimalloc feature with allocator metrics - #10046

Open
maxjtwelftree wants to merge 4 commits into
sigp:unstablefrom
maxjtwelftree:mimalloc-support
Open

maxjtwelftree wants to merge 4 commits into
sigp:unstablefrom
maxjtwelftree:mimalloc-support

Conversation

@maxjtwelftree

@maxjtwelftree maxjtwelftree commented Sep 13, 2026

Copy link
Copy Markdown

Issue Addressed

#8840

Adds an optional mimalloc feature to malloc_utils, lighthouse and lcli, so a node or a benchmark can be built with mimalloc in place of jemalloc, and exports allocator metrics for it.

This builds on the feature plumbing @0xMars42 wrote in #8884

Resolution by precedence

lighthouse/Cargo.toml and lcli/Cargo.toml both declare malloc_utils with features = ["jemalloc"] for every non-Windows target, so the jemalloc feature cannot be switched off through feature selection. Rejecting "two allocators enabled" with a compile_error! would fail every Linux and macOS build.

mimalloc therefore resolves by precedence, reusing the mechanism sysmalloc already relies on:

sysmalloc > mimalloc > jemalloc > glibc > system

Metrics

Five gauges from mi_process_info, via the extended feature of libmimalloc-sys:

Metric Meaning
mimalloc_current_rss_bytes resident set size
mimalloc_peak_rss_bytes peak resident set size
mimalloc_current_commit_bytes committed memory; the closest analogue to jemalloc_bytes_mapped
mimalloc_peak_commit_bytes peak committed memory
mimalloc_page_faults hard page faults

Verification

Every feature combination compiles and selects the expected allocator. The matrix below was run on aarch64-apple-darwin; the sysmalloc, jemalloc and mimalloc rows were independently confirmed on x86_64-unknown-linux-gnu, where each binary printed its own allocator name during the benchmark runs below.

Features allocator_name()
(default) system
sysmalloc system
jemalloc jemalloc (16K)
mimalloc mimalloc
mimalloc,jemalloc mimalloc
mimalloc,sysmalloc system
Built with Reports as Settled RSS Returned to OS Time
sysmalloc glibc 35.4 MiB 2.8% 17,471 ms
jemalloc jemalloc (4K) 23.0 MiB 90.7% 22,559 ms
mimalloc mimalloc 45.4 MiB 26.2% 13,120 ms

jemalloc returns 90% of its peak to the OS; mimalloc returns 26% and settles at 2.0x jemalloc's resident footprint. Given that Lighthouse's live memory problems are memory-shaped, #9530 being an 8.8 GB OOM, that seems like the more decision-relevant column than throughput.


Per the LLM note in CONTRIBUTING.md: I used AI assistance while working on this. I have read, built and tested every line of the diff myself, and the verification figures above are from my own machines.

Adds a `mimalloc` feature to `malloc_utils` and the `lighthouse` binary, so a
node can be built with mimalloc instead of jemalloc for comparison.

Both `lighthouse` and `lcli` declare `malloc_utils` with the `jemalloc` feature
on every non-Windows target, so that feature cannot be switched off through
feature selection. Rejecting "two allocators enabled" with `compile_error!`
would therefore break every Linux and macOS build. mimalloc instead resolves by
precedence, reusing the mechanism `sysmalloc` already relies on:

    sysmalloc > mimalloc > jemalloc > glibc > system

`scrape_allocator_metrics()` is called unconditionally by the beacon node and
validator client metrics servers, so an allocator that reports nothing leaves a
node's /metrics with no allocator data at all. This exports five gauges from
`mi_process_info` to keep that endpoint useful. The process CPU counters that
`mi_process_info` also returns are intentionally left out: they measure the
whole process rather than time spent in the allocator, and the Prometheus
process collector already reports them.

Default builds are unaffected.
@cla-assistant

cla-assistant Bot commented Sep 13, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

The benchmarks suggested on sigp#8840 use `lcli transition-blocks`, but `lcli` hardcoded
`malloc_utils` with the `jemalloc` feature and had no way to select mimalloc, so the build the
issue asks for could not be produced. Adds the passthrough.

Adds `malloc_utils` to the existing `cargo-hack` feature-powerset job. Nothing in CI compiled the
mimalloc arm, so the `cfg` precedence lattice had no regression guard; the powerset covers all 97
combinations, including the glibc arm that only selects on Linux.

Also drops an unrelated `Cargo.lock` change. Adding the dependency caused the resolver to move
`rustix` from `windows-sys` 0.52.0 to 0.59.0, which is unrelated to mimalloc and would show up as
noise in a dependency review. Reverted, and `cargo check --locked` confirms the lockfile is still
self-consistent, leaving the diff additions-only.

Softens a comment that claimed the new gauges mirror the `jemalloc_*` ones closely enough for a
dashboard to chart either allocator. The metric names differ, so they are not drop-in.
Add `mimalloc` to wordlist.txt. The book mentions it outside a code span and
the spellcheck job only skips `code` and `pre` elements.

Exclude `jemalloc-profiling` and `jemalloc-unprefixed` from the powerset check.
Neither appears in a cfg gate, so they cost build time without adding coverage.
Build artifact from running pyspelling locally, committed by accident.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant