Expand description
mimalloc is a general-purpose allocator that serves each size class from thread-local pages carved out of arenas of operating system memory, returns an object freed by any thread to the page it came from, and purges freed arena memory back to the operating system after a delay.
This module installs mimalloc as the global allocator through
MiMalloc, a GlobalAlloc whose Config lives in the binary and
is applied by the first allocation. Effective reports the options in
force and Stats reports allocator statistics.
§Configuration timing
mimalloc creates its first arena at the first allocation, which happens
before main on most targets. MiMalloc applies its Config on that
allocation, so the purge policy is in force before any memory is freed and
a reservation is the first arena threads search. A reservation requested
through the environment (MIMALLOC_RESERVE_OS_MEMORY or
MIMALLOC_RESERVE_HUGE_OS_PAGES) is made at load and comes first.
§Linking
The crate declares links = "mimalloc", so Cargo rejects a dependency
graph in which another package, such as libmimalloc-sys, declares the
same key.
Enable the local-dynamic-tls feature when the crate is built into a
shared library that is loaded with dlopen. Without it, mimalloc uses
initial-exec thread-local storage on targets other than musl. That storage
comes from a static block the loader sizes at startup, and a library
loaded later may not fit in it. The feature also has mimalloc free what
memory it can when the library is unloaded.
§Page geometry
mimalloc carves arenas into slices and derives its page sizes from the slice. Slices form chunks, and chunks form the metadata groups of an arena. One group looks like this with the default slice on 64-bit targets:
one metadata group: 8 chunks, 256 MiB
|<----- ARENA_MAX_OBJECT_SIZE: 7 chunks, 224 MiB ------>|
+-------+-------+-------+-------+-------+---------------+-------+
|chunk 0|chunk 1|chunk 2|chunk 3|chunk 4|page of its own|chunk 7|
+-------+-------+-------+-------+-------+---------------+-------+
| |
| '-------------------------------------------------------.
| |
+--------+--------+---------+-----------------+-----------------+
| page | small | medium | large | |
|metadata|1 slice |8 slices | 64 slices | ... |
| table | 64 KiB | 512 KiB | 4 MiB | |
+--------+--------+---------+-----------------+-----------------+
|<------>| ARENA_SLICE_SIZE
|<----------- ARENA_CHUNK_SIZE: 512 slices, 32 MiB ------------>|Objects up to LARGE_OBJECT_LIMIT come from thread-local pages at the
cost of a free-list operation. Larger objects get a page of their own,
which costs an arena operation per allocation and free.
The crate’s large-objects-* features raise the limit at build time by
scaling the slice (ARENA_SLICE_SIZE) and with it every page. The
geometry applies to the whole process, so only binaries should enable
them. The largest enabled feature wins.
§Large objects
Where an allocation lives depends on its size and alignment:
allocation (size, alignment)
|
+-- alignment >= metadata group (256 MiB) ---> null
|
+-- alignment > ARENA_SLICE_SIZE (64 KiB) ---> page of its own,
| mapped from the OS
v
size <= LARGE_OBJECT_LIMIT (512 KiB)?
| yes | no
v v
shared page of its size class page of its own
| |
'----------------+----------------'
v
page <= Config::arena_max_object_size?
| yes | no
v v
arena -- no room, no new arena ---> OS mappingA shared page outlives its objects for reuse. A page of its own is sized to the object rounded up (by as much as 4 MiB for the largest), and freeing the object releases it. The exception is a small object aligned beyond a slice and freed by another thread, which holds its page until the owning thread collects.
An arena keeps a released page until the Purge policy purges it. A
page spanning several chunks (see ARENA_CHUNK_SIZE) needs that many
consecutive free chunks, so a fragmented arena can make mimalloc reserve a
new arena or, failing that, map the page from the operating system. Such
a page is unmapped on release, so each allocation pays for system calls
and fresh page faults.
Pages above Config::arena_max_object_size are mapped from the
operating system the same way. The limit defaults to and is capped at
ARENA_MAX_OBJECT_SIZE, the largest page an arena can hold. A limit below
the largest shared page also maps the shared pages of larger size classes
from the operating system. Those pages are still kept for reuse.
Alignments of a whole metadata group or more are refused with null, which
a GlobalAlloc caller reports as an allocation error.
§Example
use commonware_allocator::mimalloc::{Config, MiMalloc, Purge, Reserve, Status};
use std::time::Duration;
#[global_allocator]
static GLOBAL: MiMalloc = MiMalloc::new(Config {
purge: Purge::After(Duration::from_secs(10)),
reserve: Some(Reserve::pinned(2 << 30)),
..Config::DEFAULT
});
fn main() {
assert!(commonware_allocator::mimalloc::is_global_allocator());
println!("{:?}", Status::read());
}Modules§
- metrics
- Allocator statistics exported as metrics.
Structs§
- Config
- Configuration applied by
MiMallocon its first allocation. - Effective
- The options mimalloc is running with, whether set by a
Config, the environment, or its defaults. - MiMalloc
- mimalloc as a
#[global_allocator]with aConfigapplied on the first allocation. - Reserve
- Memory reserved from the operating system before the first allocation.
- Stats
- Process-wide allocator statistics, excluding allocations that C libraries make through the system allocator.
- Status
- Process-wide configuration state.
Enums§
- Purge
- When memory freed back to an arena is purged (decommitted) to the operating system.
- Reserve
Outcome - Outcome of the reservation requested by
Config::reserve.
Constants§
- ARENA_
CHUNK_ SIZE - Size of an arena chunk, the unit reservations are rounded down to (see
Reserve::bytes). It is 512 slices, or 32 MiB at the default slice on 64-bit targets. - ARENA_
MAX_ OBJECT_ SIZE - Largest page an arena can hold, and so the cap on
Config::arena_max_object_size. mimalloc keeps page metadata at the start of every metadata group, so a page spans at most the group’s other chunks: seven chunks, or 224 MiB at the default slice on 64-bit targets. - ARENA_
SLICE_ SIZE - Size of an arena slice, the unit mimalloc carves arenas into and the smallest page size.
- LARGE_
OBJECT_ LIMIT - Largest allocation served from a shared thread-local page. It is eight
slices: 512 KiB by default, or the size named by an enabled
large-objects-*feature. Larger objects get a page of their own, which costs an arena operation per allocation and free. - MAX_
PURGE_ DELAY - Longest purge delay
Purge::Afterapplies (about 24 days). mimalloc stores the delay in milliseconds in a Clong, which is 32 bits on some platforms.
Functions§
- good_
size - Returns the block size mimalloc allocates for
sizebytes: its size class, or above the largest class,sizerounded up to an OS page. The page serving such a block may be larger. - is_
global_ allocator - Returns whether the global allocator is this crate’s mimalloc, installed
directly through
MiMallocor wrapped by another allocator. It checks a probe allocation against mimalloc’s heap region. - version
- Returns the linked mimalloc version as
major * 10000 + minor * 100 + patch.