tree: be29c9f78568d0eb6777239023a612cd590077d9 [search]
  1. src/
  2. sys/
  3. tests/
  4. .gitignore
  5. build.rs
  6. Cargo.toml
  7. README.md
contrib/rust/README.md

mimalloc for Rust

Rust bindings for mimalloc, built directly from the mimalloc sources in this repository. As usual for Rust FFI bindings, these are split into two crates:

  • mimalloc-sys (in sys/): builds and links the C library and has the raw C API.
  • mimalloc: the global allocator, heaps, and safe helpers (with the raw API re-exported as mimalloc::sys).
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).
  • Arena: reserve memory for heaps that only allocate in it (see Arenas).
  • 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.

Arenas

An arena is a large area of memory that heaps allocate from. A heap created with Heap::new_in_arena only allocates in its arena, and returns null when the arena is full.

use mimalloc::{Arena, Heap, ReserveOptions};

let options = ReserveOptions { exclusive: true, ..ReserveOptions::default() };
let arena = Arena::reserve_from_os(64 << 20, options).unwrap();
let heap = Heap::new_in_arena(arena);
  • Arena::reserve_from_os reserves fresh OS memory; Arena::from_static_memory uses memory that lives forever (such as a leaked Box); Arena::from_external_memory (unsafe) uses any other memory. They return None if the arena cannot be created.
  • An exclusive arena keeps all other heaps out; otherwise any heap can use it as well.
  • Arenas cannot be removed, so they live until the process exits.
  • Arenas need at least Arena::min_size() bytes (32 MiB on 64-bit), and their start is aligned to Arena::min_alignment() (256 MiB on 64-bit, or 64 KiB with the secure feature), so memory at an unaligned address needs max(min_size, min_alignment) + min_alignment bytes.

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 (mimalloc only)

All features except nightly are build options of the C library in mimalloc-sys (and are forwarded by mimalloc).

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 by mimalloc-sys in the following order:

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

Within this repository, use a path or git dependency:

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

To publish crates based on these, copy contrib/rust, vendor the sources into sys/mimalloc/ (cp -r ../../include ../../src ../../LICENSE sys/mimalloc/), and rename both packages (the names mimalloc and mimalloc-sys are already taken on crates.io). The mimalloc crate depends on the exact version of mimalloc-sys as its fast paths depend on internal entry points such as mi_wmalloc_small and MI_SMALL_SIZE_MAX.

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 (the C library is compiled as part of mimalloc-sys):
    [profile.dev.package.mimalloc-sys]
    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 --workspace
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.