mimalloc for Rust

Rust bindings for mimalloc, built directly from the mimalloc sources in this repository.

use mimalloc::MiMalloc;

#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc;
  • MiMalloc: the global allocator (with fast paths for small and sized allocations).
  • Heap: first-class heaps that can be shared between threads; dropping a heap keeps its live blocks valid (Heap::destroy frees them all at once).
  • sys: the raw C API (mimalloc.h).
  • Both MiMalloc and &Heap implement core::alloc::Allocator on Rust 1.100+ (or on an older nightly with the nightly feature).
  • Helpers such as collect, option_set, stats_print and stats_json.

Features

FeatureDescription
secureSecurity mitigations (guard pages, randomization, encoded free lists)
overrideAlso override malloc, free, etc. in the final binary
debugBuild mimalloc with assertions and internal checks
debug_in_debugAs debug, but only when debug_assertions are on
local_dynamic_tlsUse the local-dynamic TLS model (for dynamically loaded libraries)
win_direct_tlsUse direct TLS slots on Windows
no_thpDisable transparent huge pages by default on Linux
opt_archArchitecture specific optimizations (as -DMI_OPT_ARCH=ON)
nightlyAllocator support on nightly compilers before Rust 1.100

Architecture optimizations are also enabled automatically if the Rust target features already imply them (e.g. -C target-cpu=native).

Features can be enabled per target, e.g. to only override malloc on Linux:

[target.'cfg(target_os = "linux")'.dependencies]
mimalloc = { path = "path/to/mimalloc/contrib/rust", features = ["override"] }

Other build options can be passed as C defines in the MIMALLOC_DEFINES environment variable (separated by spaces or commas); these take precedence over the defines set by features. For example: MIMALLOC_DEFINES="MI_DEBUG=3 MI_SKIP_COLLECT_ON_EXIT=1" cargo build.

Using the crate

The C sources are found in the following order:

  1. The MIMALLOC_SRC_DIR environment variable.
  2. A vendored mimalloc/ directory next to Cargo.toml (with include/, src/, and LICENSE).
  3. The enclosing repository (../..).

Within this repository, use a path or git dependency:

[dependencies]
mimalloc = { path = ".../mimalloc/contrib/rust" }

To publish a crate based on this one, copy contrib/rust, vendor the sources into mimalloc/ (cp -r ../../include ../../src ../../LICENSE mimalloc/), and rename the package.

Performance tips

  • Enable LTO so that allocations in other crates (and std) are inlined with a statically known size and alignment (instead of going through the __rust_alloc shim):
    [profile.release]
    lto = "thin"
    
  • Optimize mimalloc in debug builds too:
    [profile.dev.package.mimalloc]
    opt-level = 3
    
  • Cross-language LTO can inline the allocation fast paths into Rust code: build with clang (matching the LLVM version of rustc) using CC=clang CFLAGS=-flto=thin and RUSTFLAGS=-Clinker-plugin-lto (see the rustc linker-plugin-lto documentation).

Testing

cargo test
cargo test --release --features secure
cargo test --features debug,override
cargo +nightly test --features nightly

The tests also run as test-rust with ctest in a CMake build (if cargo is found), using features that match the CMake configuration.