mimalloc Documentation

Mimalloc is a compact general purpose allocator with excellent performance.

13,471 stars C C 8 files ยท ~17,820 tokens
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy mimalloc on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name mimalloc --restart always microsoft/mimalloc:latest

Technical Documentation: microsoft/mimalloc

โ„น๏ธ Provenance: Multi-Tier Ingestion ยท CodeWiki Reference

Overview (`readme.md`)

v3:
v2:
v1:
   v3:

mimalloc

 

mimalloc (pronounced "me-malloc")
is a general purpose allocator with excellent performance characteristics.
Initially developed by Daan Leijen for the runtime systems of the
Koka and Lean languages.

Latest release : v3.5.3 (2026-09-16) recommended.
Latest v2 release: v2.5.2 (2026-09-12) stable, legacy.
Latest v1 release: v1.15.2 (2026-09-12) legacy.

mimalloc is a drop-in replacement for malloc and can be used in other programs
without code changes, for example, on dynamically linked ELF-based systems (Linux, BSD, etc.) you can use it as:

text
> LD_PRELOAD=/usr/lib/libmimalloc.so  myprogram

It also includes a way to dynamically override the default allocator in Windows.
Notable aspects of the design include:

  • small and consistent: the library is about 10k LOC using simple and
    consistent data structures. This makes it very suitable
    to integrate and adapt in other projects. For runtime systems it
    provides hooks for a monotonic heartbeat and deferred freeing (for
    bounded worst-case times with reference counting).
    Partly due to its simplicity, mimalloc has been ported to many systems (Windows, macOS,
    Linux, WASM, various BSD's, Haiku, MUSL, etc) and has excellent support for dynamic overriding.
    At the same time, it is an industrial strength allocator that runs (very) large scale
    distributed services on thousands of machines with excellent worst case latencies.
  • free list sharding: instead of one big free list (per size class) we have
    many smaller lists per "mimalloc page" which reduces fragmentation and
    increases locality --
    things that are allocated close in time get allocated close in memory.
    (A mimalloc page contains blocks of one size class and is usually 64KiB on a 64-bit system).
  • free list multi-sharding: the big idea! Not only do we shard the free list
    per mimalloc page, but for each page we have multiple free lists. In particular, there
    is one list for thread-local free operations, and another one for concurrent free
    operations. Free-ing from another thread can now be a single CAS without needing
    sophisticated coordination between threads. Since there will be
    thousands of separate free lists, contention is naturally distributed over the heap,
    and the chance of contending on a single location will be low -- this is quite
    similar to randomized algorithms like skip lists where adding
    a random oracle removes the need for a more complex algorithm.
  • eager page purging: when a "page" becomes empty (with increased chance
    due to free list sharding) the memory is marked to the OS as unused (reset or decommitted)
    reducing (real) memory pressure and fragmentation, especially in long running
    programs.
  • secure: mimalloc can be built in secure mode, adding guard pages,
    randomized allocation, encrypted free lists, etc. to protect against various
    heap vulnerabilities. The performance penalty is usually around 10% on average
    over our benchmarks.
  • first-class heaps: efficiently create and use multiple heaps to allocate across different regions.
    A heap can be destroyed at once instead of deallocating each object separately.
    New: v3 has true first-class heaps where one can allocate in a heap from any thread.
  • bounded: it does not suffer from blowup [1], has bounded worst-case allocation
    times (wcat) (upto OS primitives), bounded space overhead (~0.2% meta-data, with low
    internal fragmentation), and has no internal points of contention using only atomic operations.
  • fast: In our benchmarks (see below),
    mimalloc outperforms other leading allocators (jemalloc, tcmalloc, Hoard, etc),
    and often uses less memory. A nice property is that it does consistently well over a wide range
    of benchmarks. There is also good huge OS page support for larger server programs.

The documentation gives a full overview of the API.
You can read more on the design of mimalloc in the technical report which also has detailed benchmark results.

Enjoy!

Versions

There are three maintained versions of mimalloc. These are mostly equal except for how the OS memory is handled.
New development is mostly on v3, while v1 and v2 are maintained with security and bug fixes.

  • v3: recommended: simplifies the lock-free design of previous versions and improves sharing of
    memory between threads. On certain large workloads this version may use
    (much) less memory. Also supports true first-class heaps (that can allocate from any thread)
    and has more efficient heap-walking (for the CPython GC for example).
    (release tags: v3.x, development branch dev3).
  • v2: stable legacy mimalloc version. Uses thread-local segments to reduce fragmentation. (release tags: v2.x, development branch dev2 and main)
  • v1: legacy version: initial design of mimalloc (release tags: v1.x, development branch dev).
    Send PR's against this version if possible (and otherwise dev3).

Releases

  • 2026-09-16, v3.5.3: (v3) critical bug fix (where the first new on a thread could
    fail on some platforms #1398). Fix bug with mi_free_size on overaligned small allocations (#1400).

  • 2026-09-12, v3.5.2, v2.5.2, v1.15.2: (v3) Reduced cache contention, improved mi_malloc_csize,
    improved zero'ing of small blocks, mi_wmalloc variants for runtime systems, always enable detailed
    statistics. Experimental support for profiling hooks (mimalloc-profile.h).

  • 2026-09-01: Added a readme section on getting the best performance.

  • 2026-09-01, v3.5.1, v2.5.1, v1.15.1: (v3) Yet better performance for free calls.
    (v3) Added mi_free_small(_nonnull) for fast small allocations, and mi_free_csize(_nonnull) for inlined constant size free-ing.
    (v3) Improved MI_OPT_ARCH options; on arm64, defaults to armv8.3 on Apple and armv8.1 otherwise.
    (v3) Default to -DMI_ALLOW_THP=FULL on Linux, where we never split transparent huge pages (THP) during purging (#1282). This
    may increase rss but can also improve performance. Use -DMI_ALLOW_THP=OFF to disable the use of THP.
    (v3) Improved cache behavior for small allocations. Improved riscV support. Various small build fixes.

  • 2026-08-18, v1.15.0, v2.5.0, v3.5.0: (v3) slightly better performance for free
    using aligned chunks, cleanup cmake options, require armv8.3 (with MI_OPT_ARCH) for
    faster load-acquire, increase retired page count from 1 to 3, faster double free
    detection in secure mode, use faster atomics for the arena bitmaps (thank you Alan
    Andrade, #1346), faster pagemap lookup.
    Other: fix numa sparse node count detection (#1365), add theap stats retrieval,
    use __builtin_thread_pointer on riscV (#1363), fix C mode compilation on x86 with
    msvc (#1361), improved mingw-ucrt64 support.

  • 2026-08-05, v1.9.15, v2.4.5, v3.4.5: Fix compilation with xmalloc (#1353), make the build deterministic (#1355),
    mi_zalloc_aligned fix (#763), improve support for mingw (ucrt64), fix fputs fallback on windows (#1354), (v3): use proper
    lock backoff for first-class heap deletion, improved riscv64 codegen.

  • 2026-08-01, v1.9.14, v2.4.4, v3.4.4: various bug and security fixes through Opus 5 LLM audit (issue #1271, by @Zoxc).
    (v3): use pthreads by default on macOS (issue #1333, issue #1327), fix glibc 2.44 crash (issue #1341), fix alignment check for realloc_aligned. (v1,v2,v3): Add initial mingw support,
    set errno on allocation errors, improved double-free checks and size checks in secure mode, enable
    build for universal windows platform and xbox (pr #1340), fix numa node detection when numa nodes are sparse.

  • 2026-07-20, v3.4.3: revert TLS slots on macOS to 108/109 (issue #1333).

  • 2026-07-14, v1.9.11, v2.4.1, v3.4.1: various bug and security fixes through LLM audit (by @Zoxc).
    Fix issue with using OS memory instead of arenas for > 4GiB memory usage (v3), fix concurrency bug in concurrent
    heap destroy (v3), detect riscV virtual address bits at runtime, add riscV TLS support, reduce spinlock waits (v2),
    use TLS slots 126/127 on macOS (v3), and other small fixes. All metadata is now separated from heap objects in v3.

  • 2026-04-29, v1.9.10, v2.3.2, v3.3.2: various bug and security fixes through LLM audit (by @Zoxc).
    Only increase minimal purge size automatically if allow_thp is set to 2. Enable large OS alignment
    on all platforms (fixing OS large pages on Windows). Fix accounting of committed memory on Linux/macOS.
    Update MSVC atomics implementation when using C mode. Upstream Emscripten fixes. Proper atomic do-once
    implementation.

  • 2026-04-20, v1.9.9, v2.3.1, v3.3.1: various bug and security fixes. Special thanks to
    @jinpzhanAMD, @res2k, and @GoldJohnKing for their help in improving Windows finalization, and
    @Zoxc for his help in finding various issues.

  • Older release notes

Special thanks to:

  • Sergiy Kuryata for his contributions on reducing memory commit -- especially on Windows with the Windows thread pool (now implemented in v3).
  • David Carlier (@devnexen) for his many contributions, and making
    mimalloc work better on many less common operating systems, like Haiku, Dragonfly, etc.
  • Mary Feofanova (@mary3000), Evgeniy Moiseenko, and Manuel Pรถter (@mpoeter) for making mimalloc TSAN checkable, and finding
    memory model bugs using the genMC model checker.
  • Weipeng Liu (@pongba), Zhuowei Li, Junhua Wang, and Jakub Szymanski, for their early support of mimalloc and deployment
    at large scale services, leading to many improvements in the mimalloc algorithms for large workloads.
  • Jason Gibson (@jasongibson) for exhaustive testing on large scale workloads and server environments, and finding complex bugs
    in (early versions of) mimalloc.
  • Manuel Pรถter (@mpoeter) and Sam Gross(@colesbury) for finding an ABA concurrency issue in abandoned segment reclamation. Sam also created the no GIL Python fork which
    uses mimalloc internally.

Usage

mimalloc is used in various large scale low-latency services and programs, for example:





Building

Windows

Open ide/vs2022/mimalloc.sln in Visual Studio 2022 and build.
The mimalloc-lib project builds a static library (in out/msvc-x64), while the
mimalloc-override-dll project builds a DLL for overriding malloc
in the entire program.

Linux, macOS, BSD, etc.

We use cmake as the build system:

text
> mkdir -p out/release
> cd out/release
> cmake ../..
> make

This builds the library as a shared (dynamic)
library (.so or .dylib), a static library (.a), and
as a single object file (.o).

> sudo make install (install the library and header files in /usr/local/lib and /usr/local/include)

You can build the debug version which does many internal checks and
maintains detailed statistics as:

text
> mkdir -p out/debug
> cd out/debug
> cmake -DCMAKE_BUILD_TYPE=Debug ../..
> make

This will name the shared library as libmimalloc-debug.so.

Finally, you can build a secure version that uses guard pages, encrypted free lists, etc., as:

text
> mkdir -p out/secure
> cd out/secure
> cmake -DMI_SECURE=ON ../..
> make

This will name the shared library as libmimalloc-secure.so.
Use cmake ../.. -LH to see all the available build options.

The examples use the default compiler. If you like to use another, use:

text
> CC=clang CXX=clang++ cmake ../..

Cmake with Visual Studio

You can also use cmake on Windows. Open a Visual Studio 2022 development prompt
and invoke cmake with the right generator
and architecture, like:

text
> cmake ..\.. -G "Visual Studio 17 2022" -A x64 -DMI_OVERRIDE=ON

The cmake build type is specified when actually building, for example:

text
> cmake --build . --config=Release

You can also install the LLVM toolset
on Windows to build with the clang-cl compiler directly:

text
> cmake ../.. -G "Visual Studio 17 2022" -T ClangCl

Single Source

You can also directly build the single src/static.c file as part of your project without
needing cmake at all. Make sure to also add the mimalloc include directory to the include path.

Using the Library

The preferred usage is including <mimalloc.h>, linking with
the shared- or static library, and using the mi_malloc API exclusively for allocation. For example,

text
> gcc -o myprogram -lmimalloc myfile.c

mimalloc uses only safe OS calls (mmap and VirtualAlloc) and can co-exist
with other allocators linked to the same program.
If you use cmake, you can simply use:

text
find_package(mimalloc 1.8 REQUIRED)

in your CMakeLists.txt to find a locally installed mimalloc. Then use either:

text
target_link_libraries(myapp PUBLIC mimalloc)

to link with the shared (dynamic) library, or:

text
target_link_libraries(myapp PUBLIC mimalloc-static)

to link with the static library. See test\CMakeLists.txt for an example.

For best performance in C++ programs, it is also recommended to override the
global new and delete operators. For convenience, mimalloc provides
mimalloc-new-delete.h which does this for you -- just include it in a single(!) source file in your project.
In C++, mimalloc also provides the mi_stl_allocator struct which implements the std::allocator
interface.

You can pass environment variables to print verbose messages (MIMALLOC_VERBOSE=1)
and statistics (MIMALLOC_SHOW_STATS=1) (in the debug version):

text
/* Detailed source-code truncated for AI context efficiency. */

The above model of using the mi_ prefixed API is not always possible
though in existing programs that already use the standard malloc interface,
and another option is to override the standard malloc interface
completely and redirect all calls to the mimalloc library instead .

Environment Options

You can set further options either programmatically (using mi_option_set), or via environment variables:

  • MIMALLOC_SHOW_STATS=1: show statistics when the program terminates.
  • MIMALLOC_VERBOSE=1: show verbose messages (including statistics).
  • MIMALLOC_SHOW_ERRORS=1: show error and warning messages.

Advanced options:

  • MIMALLOC_ARENA_EAGER_COMMIT=2: turns on eager commit for the large arenas (usually 1GiB) from which mimalloc
    allocates segments and pages. Set this to 2 (default) to
    only enable this on overcommit systems (e.g. Linux). Set this to 1 to enable explicitly on other systems
    as well (like Windows or macOS) which may improve performance (as the whole arena is committed at once).
    Note that eager commit only increases the commit but not the actual the peak resident set
    (rss) so it is generally ok to enable this.
  • MIMALLOC_PURGE_DELAY=N: the delay in N milli-seconds (by default 1000 in v3) after which mimalloc will purge
    OS pages that are not in use. This signals to the OS that the underlying physical memory can be reused which
    can reduce memory fragmentation especially in long running (server) programs. Setting N to 0 purges immediately when
    a page becomes unused which can improve memory usage but also decreases performance.
    Setting it to -1 disables purging completely.
  • MIMALLOC_PURGE_DECOMMITS=1: By default "purging" memory means unused memory is decommitted (MEM_DECOMMIT on Windows,
    MADV_DONTNEED (which decresease rss immediately) on mmap systems). Set this to 0 to instead "reset" unused
    memory on a purge (MEM_RESET on Windows, generally MADV_FREE (which does not decrease rss immediately) on mmap systems).
    Mimalloc generally does not "free" OS memory but only "purges" OS memory, in other words, it will keep virtual
    address ranges, but decommits within those ranges (to make the underlying physical memory available to other processes).

Further options for large workloads and services:

  • MIMALLOC_ALLOW_THP=[0,1,2]: When set to 0, the use of transparent huge pages (THP) is disabled for the process that mimalloc
    runs in, and otherwise it is enabled whenever THP is enabled in the OS ([always] or [madvise]). If set to 2 (default on Linux),
    mimalloc also sets the MIMALLOC_MINIMAL_PURGE_SIZE in v3 to 2MiB to avoid potentially breaking up transparent huge pages when
    purging memory which is better for performance (but may increase the rss!). On Android the default setting is 0 to reduce rss.
  • MIMALLOC_USE_NUMA_NODES=N: pretend there are at most N NUMA nodes. If not set, the actual NUMA nodes are detected
    at runtime. Setting N to 1 may avoid problems in some virtual environments. Also, setting it to a lower number than
    the actual NUMA nodes is fine and will only cause threads to potentially allocate more memory across actual NUMA
    nodes (but this can happen in any case as NUMA local allocation is always a best effort but not guaranteed).
  • MIMALLOC_ALLOW_LARGE_OS_PAGES=0: Set to 1 to use large OS pages (2 or 4MiB) when available; for some workloads this can
    significantly improve performance. However, large OS pages cannot be purged or shared with other processes so may lead
    to increased memory usage in some cases.
    Use MIMALLOC_VERBOSE to check if the large OS pages are enabled -- usually one needs
    to explicitly give permissions for large OS pages (as on Windows and Linux). However, sometimes
    the OS is very slow to reserve contiguous physical memory for large OS pages so use with care on systems that
    can have fragmented memory (for that reason, we generally recommend to use MIMALLOC_RESERVE_HUGE_OS_PAGES instead whenever possible).
  • MIMALLOC_RESERVE_HUGE_OS_PAGES=N: where N is the number of 1GiB huge OS pages. This reserves the huge pages at
    startup and sometimes this can give a large (latency) performance improvement on big workloads.
    Usually it is better to not use MIMALLOC_ALLOW_LARGE_OS_PAGES=1 in combination with this setting. Just like large
    OS pages, use with care as reserving
    contiguous physical memory can take a long time when memory is fragmented (but reserving the huge pages is done at
    startup only once).
    Note that we usually need to explicitly give permission for huge OS pages (as on Windows and Linux)).
    The huge pages are usually allocated evenly among NUMA nodes.
    We can use MIMALLOC_RESERVE_HUGE_OS_PAGES_AT=N where N is the numa node (starting at 0) to allocate all
    the huge pages at a specific numa node instead.

Use caution when using fork in combination with either large or huge OS pages: on a fork, the OS uses copy-on-write
for all pages in the original process including the huge OS pages. When any memory is now written in that area, the
OS will copy the entire 1GiB huge page (or 2MiB large page) which can cause the memory usage to grow in large increments.

Secure Mode

mimalloc can be build in secure mode by using the -DMI_SECURE=ON flags in cmake. This build enables various mitigations
to make mimalloc more robust against exploits. In particular:

  • All internal mimalloc page meta-data is surrounded by guard pages (so a buffer overflow exploit cannot reach into the metadata).
  • All free list pointers are
    encoded
    with per-page keys which is used both to prevent overwrites with a known pointer, as well as to detect heap corruption.
  • Double free's are detected (and ignored).
  • The free lists are initialized in a random order and allocation randomly chooses between extension and reuse within a page to
    mitigate against attacks that rely on a predicable allocation order. Similarly, the larger heap blocks allocated by mimalloc
    from the OS are also address randomized.
  • If using -DMI_SECURE=FULL there will also be guard pages at the end of each (64KiB) mimalloc page (thus interleaving
    valid block data with inaccessible gaps). This setting is not recommended in general as it is more expensive and can lead to
    reaching the maximum VMA limit on Linux systems if the heap gets too large.

As always, evaluate with care as part of an overall security strategy as all of the above are mitigations but not guarantees.

Debug Mode

When mimalloc is built using debug mode, (-DCMAKE_BUILD_TYPE=Debug) (or when using -DMI_DEBUG=ON explicitly),
various checks are done at runtime to catch development errors.

  • Statistics are maintained in detail for each object size. They can be shown using MIMALLOC_SHOW_STATS=1 at runtime.
  • All objects have padding at the end to detect (byte precise) heap block overflows.
  • Double free's, and freeing invalid heap pointers are detected.
  • Corrupted free-lists and some forms of use-after-free are detected.

Guarded Mode

mimalloc can be build in guarded mode using the -DMI_GUARDED=ON flags in cmake.
This is ON by default when building a debug version of mimalloc.
Guarded mode enables placing OS guard pages behind certain object allocations to catch buffer overflows as they occur.
This can be invaluable to catch buffer-overflow bugs in large programs. However, it also means that any object
allocated with a guard page takes at least 8 KiB memory for the guard page and its alignment. As such, allocating
a guard page for every allocation may be too expensive both in terms of memory, and in terms of performance with
many system calls. Therefore, there are various environment variables (and options) to tune this:

  • MIMALLOC_GUARDED_SAMPLE_RATE=N: Set the sample rate to N (by default 0). This mode places a guard page
    behind every N suitable object allocations (per thread). Since the performance in guarded mode without placing
    guard pages is close to release mode, this can be used to enable guard pages even in production to catch latent
    buffer overflow bugs. Set the sample rate to 1 to guard every object, and to 0 to place no guard pages at all.

  • MIMALLOC_GUARDED_SAMPLE_SEED=N: Start sampling at N (by default random). Can be used to reproduce a buffer
    overflow if needed.

  • MIMALLOC_GUARDED_MIN=N, MIMALLOC_GUARDED_MAX=N: Minimal and maximal rounded object sizes for which a guard
    page is considered (0 and 1GiB respectively). If you suspect a buffer overflow occurs with an object of size
    141, set the minimum and maximum to 148 and the sample rate to 1 to have all of those guarded.

  • MIMALLOC_GUARDED_PRECISE=1: If we have an object of size 13, we would usually place it an aligned 16 bytes in
    front of the guard page. Using MIMALLOC_GUARDED_PRECISE places it exactly 13 bytes before a page so that even
    a 1 byte overflow is detected. This violates the C/C++ minimal alignment guarantees though so use with care.

Overriding Standard Malloc

Overriding the standard malloc (and new) can be done either dynamically or statically.

Static override

On Unix like systems, you can statically link with mimalloc to override the standard
malloc interface. The recommended way is to link the final program with the
mimalloc single object file (mimalloc.o). We use
an object file instead of a library file as linkers give preference to
that over archives to resolve symbols. To ensure that the standard
malloc interface resolves to the mimalloc library, link it as the first
object file. For example:

text
> gcc -o myprogram mimalloc.o  myfile1.c ...

Another way to override statically that works on all platforms, is to
link statically to mimalloc (as shown in the introduction) and include a
header file in each source file that re-defines malloc etc. to mi_malloc.
This is provided by mimalloc-override.h. This only works
reliably though if all sources are
under your control or otherwise mixing of pointers from different heaps may occur!

Note: recently we also enabled static overloading on Windows. In that case you need
to link with the static CRT release runtime (/MT) and link with the static
mimalloc(-debug).obj (to take precendence over the definitions in the CRT library).

Dynamic override

This is the recommended way to override the standard malloc interface.

Dynamic Override on Linux, BSD

On these ELF-based systems we preload the mimalloc shared
library so all calls to the standard malloc interface are
resolved to the mimalloc library.

text
> env LD_PRELOAD=/usr/lib/libmimalloc.so myprogram

You can set extra environment variables to check that mimalloc is running,
like:

text
> env MIMALLOC_VERBOSE=1 LD_PRELOAD=/usr/lib/libmimalloc.so myprogram

or run with the debug version to get detailed statistics:

text
> env MIMALLOC_SHOW_STATS=1 LD_PRELOAD=/usr/lib/libmimalloc-debug.so myprogram

Dynamic Override on MacOS

On macOS we can also preload the mimalloc shared
library so all calls to the standard malloc interface are
resolved to the mimalloc library.

text
> env DYLD_INSERT_LIBRARIES=/usr/lib/libmimalloc.dylib myprogram

Note that certain security restrictions may apply when doing this from
the shell.

Dynamic Override on Windows

We use a separate redirection DLL to override mimalloc on Windows
such that we redirect all malloc/free calls that go through the (dynamic) C runtime allocator,
including those from other DLL's or libraries. As it intercepts all allocation calls on a low level,
it can be used on large programs that include other 3rd party components.
There are four requirements to make the overriding work well:

  1. Use the C-runtime library as a DLL (using the /MD or /MDd switch).

  2. Link your program explicitly with the mimalloc.dll.lib export library for the mimalloc.dll.
    (which must be compiled with -DMI_OVERRIDE=ON, which is the default though).
    To ensure the mimalloc.dll is actually loaded at run-time it is easiest
    to insert some call to the mimalloc API in the main function, like mi_version()
    (or use the /include:mi_version switch on the linker command, or
    similarly, #pragma comment(linker, "/include:mi_version") in some source file).
    See the mimalloc-test-override project for an example on how to use this.

  3. The mimalloc-redirect.dll must be put in the same directory as the main
    mimalloc.dll at runtime (as it is a dependency of that DLL).
    The redirection DLL ensures that all calls to the C runtime malloc API get
    redirected to mimalloc functions (which reside in mimalloc.dll).

  4. Ensure the mimalloc.dll comes as early as possible in the import
    list of the final executable (so it can intercept all potential allocations).
    You can use minject -l <exe> to check this if needed.

For best performance on Windows with C++, it is also recommended to also override
the new/delete operations (by including mimalloc-new-delete.h
a single(!) source file in your project).

The environment variable MIMALLOC_DISABLE_REDIRECT=1 can be used to disable dynamic
overriding at run-time. Use MIMALLOC_VERBOSE=1 to check if mimalloc was successfully
redirected.

For different platforms than x64, you may need a specific redirection dll.
Furthermore, we cannot always re-link an executable or ensure mimalloc.dll comes
first in the import table. In such cases the minject tool can be used
to patch the executable's import tables.

Getting the best performance

Consider the following build options (v3):

  • -DMI_OPT_ARCH=ON (by default ON on arm64): enables architecture specific optimizations.
    This uses -march=haswell;-march=avx2 on x64 (available since 2013), -march=armv8.1 on arm64 (2016),
    and -march=rv64gcb_zacas on riscV (2023).
    Each benefits mimalloc with better bit operations and/or native atomic operations (but also, if your
    emulator or hardware does not support these extensions the program will fail with an illegal instruction).
    On Apple arm64 the default is -march=armv8.3 (which is supported on the M1 and better) which includes
    efficient load-acquire instructions which mimalloc uses. For riscV the corresponding zalasr extension
    can be enabled as -DMI_OPT_ARCH=rv64gcb_zacas_zalasr when your hardware supports it.

  • -DMI_ALLOW_THP=OFF: disabling THP can reduce the rss of certain programs significantly.

  • -DMI_ALLOW_THP=FULL: enabling THP can increase performance of certain programs significantly. This setting
    still disables THP if the OS THP setting is configured as [never].

  • -DMI_FREE_IS_CHECKED=ON (by default ON in secure mode): slightly slower performance but checks validity
    of every pointer passed to mi_free. Sometimes needed when overriding malloc/free process wide.
    Note also that mi_cfree (checked free) always checks the validity of pointers passed to it which can
    also be used if appropiate without needing to check all pointers process wide.

In the source code:

  • Use mi_zalloc for zero initialized allocations.

  • Use the typed macros mi_malloc_tp etc. as these are both more safe and also use mi_malloc_csize internally.

  • Use mi_malloc_csize/mi_free_csize etc. when the allocated or free'd size is a constant as these are inlined
    and statically redirect to mi_malloc_small/mi_free_small when possible.
    These are also used by the C++ mimalloc-new-delete.h sized overrides.
    You can use mi_free_csize_nonnull when the pointer is guaranteed to be not NULL as well.

  • Use mi_malloc_small when the allocation size is guaranteed to be less than MI_SMALL_SIZE_MAX (1KiB) for faster allocations.

  • Use mi_free_small when the pointer was returned from mi_malloc_small (and guaranteed to have a
    size of less than MI_SMALL_SIZE_MAX). Use mi_free_small_nonnull when the pointer is guaranteed to be not NULL as well.

For run-time systems and compilers (like Koka, Lean, Rust (?) etc.), we can do slightly better still.

  • If the allocation size is statically known, use mi_malloc_csize and mi_free_csize etc. when possible.
    (or directly mi_malloc_small/mi_free_small).

  • If the runtime already carries thread local state, it may be faster to get the default theap for each thread
    up-front (mi_theap_get_default()) and use the bestest mi_theap_malloc(_small) etc. passing the theap pointer directly.
    This avoids having mimalloc look up the thread local pointer all the time and
    skips a theap NULL check. Whether this is
    faster depends a bit on the OS implementation of thread local variables.

Tools

Generally, we recommend using the standard allocator with memory tracking tools, but mimalloc
can also be build to support the address sanitizer or the excellent Valgrind tool.
Moreover, it can be build to support Windows event tracing (ETW).
This has a small performance overhead but does allow detecting memory leaks and byte-precise
buffer overflows directly on final executables. See also the test/test-wrong.c file to test with various tools.

Valgrind

To build with valgrind support, use the MI_TRACK_VALGRIND=ON cmake option:

text
> cmake ../.. -DMI_TRACK_VALGRIND=ON

This can also be combined with secure mode or debug mode.
You can then run your programs directly under valgrind:

text
> valgrind <myprogram>

If you rely on overriding malloc/free by mimalloc (instead of using the mi_malloc/mi_free API directly),
you also need to tell valgrind to not intercept those calls itself, and use:

text
> MIMALLOC_SHOW_STATS=1 valgrind  --soname-synonyms=somalloc=*mimalloc* -- <myprogram>

By setting the MIMALLOC_SHOW_STATS environment variable you can check that mimalloc is indeed
used and not the standard allocator. Even though the Valgrind option
is called --soname-synonyms, this also works when overriding with a static library or object file.
To dynamically override mimalloc using LD_PRELOAD together with valgrind, use:

text
> valgrind --trace-children=yes --soname-synonyms=somalloc=*mimalloc* /usr/bin/env LD_PRELOAD=/usr/lib/libmimalloc.so -- <myprogram>

See also the test/test-wrong.c file to test with valgrind.

Valgrind support is in its initial development -- please report any issues.

ASAN

To build with the address sanitizer, use the -DMI_TRACK_ASAN=ON cmake option:

text
> cmake ../.. -DMI_TRACK_ASAN=ON

This can also be combined with secure mode or debug mode.
You can then run your programs as:'

text
> ASAN_OPTIONS=verbosity=1 <myprogram>

When you link a program with an address sanitizer build of mimalloc, you should
generally compile that program too with the address sanitizer enabled.
For example, assuming you build mimalloc in out/debug:

text
clang -g -o test-wrong -Iinclude test/test-wrong.c out/debug/libmimalloc-asan-debug.a -lpthread -fsanitize=address -fsanitize-recover=address

Since the address sanitizer redirects the standard allocation functions, on some platforms (macOSX for example)
it is required to compile mimalloc with -DMI_OVERRIDE=OFF.
Address sanitizer support is in its initial development -- please report any issues.

ETW

Event tracing for Windows (ETW) provides a high performance way to capture all allocations though
mimalloc and analyze them later. To build with ETW support, use the -DMI_TRACK_ETW=ON cmake option.

You can then capture an allocation trace using the Windows performance recorder (WPR), using the
src/prim/windows/etw-mimalloc.wprp profile. In an admin prompt, you can use:

text
> wpr -start src\prim\windows\etw-mimalloc.wprp -filemode
> <my_mimalloc_program>
> wpr -stop <my_mimalloc_program>.etl

and then open <my_mimalloc_program>.etl in the Windows Performance Analyzer (WPA), or
use a tool like TraceControl that is specialized for analyzing mimalloc traces.

Performance

Last update: 2021-01-30.
(Note 2026-09-01: this is a while ago now, many of these allocators have improved over time as well. YMMV.)

We tested mimalloc against many other top allocators over a wide
range of benchmarks, ranging from various real world programs to
synthetic benchmarks that see how the allocator behaves under more
extreme circumstances. In our benchmark suite, mimalloc outperforms other leading
allocators (jemalloc, tcmalloc, Hoard, etc), and has a similar memory footprint. A nice property is that it
does consistently well over the wide range of benchmarks.

General memory allocators are interesting as there exists no algorithm that is
optimal -- for a given allocator one can usually construct a workload
where it does not do so well. The goal is thus to find an allocation
strategy that performs well over a wide range of benchmarks without
suffering from (too much) underperformance in less common situations.

As always, interpret these results with care since some benchmarks test synthetic
or uncommon situations that may never apply to your workloads. For example, most
allocators do not do well on xmalloc-testN but that includes even the best
industrial allocators like jemalloc and tcmalloc that are used in some of
the world's largest systems (like Chrome or FreeBSD).

Also, the benchmarks here do not measure the behaviour on very large and long-running server workloads,
or worst-case latencies of allocation. Much work has gone into mimalloc to work well on such
workloads (for example, to reduce virtual memory fragmentation on long-running services)
but such optimizations are not always reflected in the current benchmark suite.

We show here only an overview -- for
more specific details and further benchmarks we refer to the
technical report.
The benchmark suite is automated and available separately
as mimalloc-bench.

Benchmark Results on a 16-core AMD 5950x (Zen3)

Testing on the 16-core AMD 5950x processor at 3.4Ghz (4.9Ghz boost), with
32GiB memory at 3600Mhz, running Ubuntu 20.04 with glibc 2.31 and GCC 9.3.0.

We measure three versions of mimalloc: the main version mi (tag:v1.7.0),
the new v2.0 beta version as xmi (tag:v2.0.0), and the main version in secure mode as smi (tag:v1.7.0).

The other allocators are
Google's tcmalloc (tc, tag:gperftools-2.8.1) used in Chrome,
Facebook's jemalloc (je, tag:5.2.1) by Jason Evans used in Firefox and FreeBSD,
the Intel thread building blocks allocator (tbb, tag:v2020.3),
rpmalloc (rp,tag:1.4.1) by Mattias Jansson,
the original scalable Hoard (git:d880f72) allocator by Emery Berger [1],
the memory compacting Mesh (git:67ff31a) allocator by
Bobby Powers et al [8],
and finally the default system allocator (glibc, 2.31) (based on PtMalloc2).

Any benchmarks ending in N run on all 32 logical cores in parallel.
Results are averaged over 10 runs and reported relative
to mimalloc (where 1.2 means it took 1.2× longer to run).
The legend also contains the overall relative score between the
allocators where 100 points is the maximum if an allocator is fastest on
all benchmarks.

The single threaded cfrac benchmark by Dave Barrett is an implementation of
continued fraction factorization which uses many small short-lived allocations.
All allocators do well on such common usage, where mimalloc is just a tad
faster than tcmalloc and
jemalloc.

The leanN program is interesting as a large realistic and
concurrent workload of the Lean
theorem prover compiling its own standard library, and there is a 13%
speedup over tcmalloc. This is
quite significant: if Lean spends 20% of its time in the
allocator that means that mimalloc is 1.6× faster than tcmalloc
here. (This is surprising as that is not measured in a pure
allocation benchmark like alloc-test. We conjecture that we see this
outsized improvement here because mimalloc has better locality in
the allocation which improves performance for the other computations
in a program as well).

The single threaded redis benchmark again show that most allocators do well on such workloads.

The larsonN server benchmark by Larson and Krishnan [2] allocates and frees between threads. They observed this
behavior (which they call bleeding) in actual server applications, and the benchmark simulates this.
Here, mimalloc is quite a bit faster than tcmalloc and jemalloc probably due to the object migration between different threads.

The mstressN workload performs many allocations and re-allocations,
and migrates objects between threads (as in larsonN). However, it also
creates and destroys the N worker threads a few times keeping some objects
alive beyond the life time of the allocating thread. We observed this
behavior in many larger server applications.

The rptestN benchmark
by Mattias Jansson is a allocator test originally designed
for rpmalloc, and tries to simulate realistic allocation patterns over
multiple threads. Here the differences between allocators become more apparent.

The second benchmark set tests specific aspects of the allocators and
shows even more extreme differences between them.

The alloc-test, by
OLogN Technologies AG, is a very allocation intensive benchmark doing millions of
allocations in various size classes. The test is scaled such that when an
allocator performs almost identically on alloc-test1 as alloc-testN it
means that it scales linearly.

The sh6bench and sh8bench benchmarks are
developed by MicroQuill as part of SmartHeap.
In sh6bench mimalloc does much
better than the others (more than 2.5× faster than jemalloc).
We cannot explain this well but believe it is
caused in part by the "reverse" free-ing pattern in sh6bench.
The sh8bench is a variation with object migration
between threads; whereas tcmalloc did well on sh6bench, the addition of object migration causes it to be 10× slower than before.

The xmalloc-testN benchmark by Lever and Boreham [5] and Christian Eder, simulates an asymmetric workload where
some threads only allocate, and others only free -- they observed this pattern in
larger server applications. Here we see that
the mimalloc technique of having non-contended sharded thread free
lists pays off as it outperforms others by a very large margin. Only rpmalloc, tbb, and glibc also scale well on this benchmark.

The cache-scratch benchmark by Emery Berger [1], and introduced with
the Hoard allocator to test for passive-false sharing of cache lines.
With a single thread they all
perform the same, but when running with multiple threads the potential allocator
induced false sharing of the cache lines can cause large run-time differences.
Crundal [6] describes in detail why the false cache line sharing occurs in the tcmalloc design, and also discusses how this
can be avoided with some small implementation changes.
Only the tbb, rpmalloc and mesh allocators also avoid the
cache line sharing completely, while Hoard and glibc seem to mitigate
the effects. Kukanov and Voss [7] describe in detail
how the design of tbb avoids the false cache line sharing.

On a 36-core Intel Xeon

For completeness, here are the results on a big Amazon
c5.18xlarge instance
consisting of a 2×18-core Intel Xeon (Cascade Lake) at 3.4GHz (boost 3.5GHz)
with 144GiB ECC memory, running Ubuntu 20.04 with glibc 2.31, GCC 9.3.0, and
Clang 10.0.0. This time, the mimalloc allocators (mi, xmi, and smi) were
compiled with the Clang compiler instead of GCC.
The results are similar to the AMD results but it is interesting to
see the differences in the larsonN, mstressN, and xmalloc-testN benchmarks.

Peak Working Set

The following figure shows the peak working set (rss) of the allocators
on the benchmarks (on the c5.18xlarge instance).

Note that the xmalloc-testN memory usage should be disregarded as it
allocates more the faster the program runs. Similarly, memory usage of
larsonN, mstressN, rptestN and sh8bench can vary depending on scheduling and
speed. Nevertheless, we hope to improve the memory usage on mstressN
and rptestN (just as cfrac, larsonN and sh8bench have a small working set which skews the results).

References

  • [1] Emery D. Berger, Kathryn S. McKinley, Robert D. Blumofe, and Paul R. Wilson.
    Hoard: A Scalable Memory Allocator for Multithreaded Applications
    the Ninth International Conference on Architectural Support for Programming Languages and Operating Systems (ASPLOS-IX). Cambridge, MA, November 2000.
    pdf

  • [2] P. Larson and M. Krishnan. Memory allocation for long-running server applications.
    In ISMM, Vancouver, B.C., Canada, 1998. pdf

  • [3] D. Grunwald, B. Zorn, and R. Henderson.
    Improving the cache locality of memory allocation. In R. Cartwright, editor,
    Proceedings of the Conference on Programming Language Design and Implementation, pages 177โ€“186, New York, NY, USA, June 1993. pdf

  • [4] J. Barnes and P. Hut. A hierarchical O(n*log(n)) force-calculation algorithm. Nature, 324:446-449, 1986.

  • [5] C. Lever, and D. Boreham. Malloc() Performance in a Multithreaded Linux Environment.
    In USENIX Annual Technical Conference, Freenix Session. San Diego, CA. Jun. 2000.
    Available at https://github.com/kuszmaul/SuperMalloc/tree/master/tests

  • [6] Timothy Crundal. Reducing Active-False Sharing in TCMalloc. 2016. CS16S1 project at the Australian National University. pdf

  • [7] Alexey Kukanov, and Michael J Voss.
    The Foundations for Scalable Multi-Core Software in Intel Threading Building Blocks.
    Intel Technology Journal 11 (4). 2007

  • [8] Bobby Powers, David Tench, Emery D. Berger, and Andrew McGregor.
    Mesh: Compacting Memory Management for C/C++
    In Proceedings of the 40th ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI'19), June 2019, pages 333-โ€“346.

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.microsoft.com.

When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
provided by the bot. You will only need to do this once across all repos using our CLA.

Older Release Notes

  • 2026-04-15, v1.9.8, v2.3.0, v3.3.0: initial support for github (binary) releases,
    fix visiting of full pages during collection (performance),
    fix THP alignment (performance), fix arm64 cross-compilation on Windows, enable guard pages in debug mode,
    always use uncommitted areas between arenas (security), enable static overloading of malloc etc. on Windows with the
    static CRT (by @Noxybot), fix TLS slot leak on Windows (v3), enable clean DLL load/unload with statically linked
    mimalloc (v3), fix race in mi_heap_destroy (v3), by default put page meta info separate from allocated
    objects (v3,security), fix C++ overrides for emscripten. Various bugs found by DeepTest include:
    fix offset for mi_heap_realloc_aligned, fix mi_(w)dupenv_s buffer size, fix potential overflow in size options,
    and error codes for mi_reallocarr(ay).

  • 2026-02-03, v3.2.8 (rc3): Fix thread reinitialize issue on macOS. Fix SIMD codegen bug on older
    GCC versions. Extend Windows TLS slot limit from 64 to 1088. Report commit statistics more precise.
    Fixes issue in free-page search in arenas.

  • 2026-01-15, v1.9.7, v2.2.7, v3.2.7 (rc2): Fix zero initializing blocks that were OS allocated.
    For v3 various bug and performance fixes. Fix Debian 32-bit compilation.

  • 2026-01-08, v1.9.6, v2.2.6, v3.2.6 (rc1): Important bug fixes. Many improvements to v3 including
    true first-class heaps where one can allocate in heap from any thread, and track statistics per heap as well.
    Added MIMALLOC_ALLOW_THP option. This is by default enabled except on Android. When THP is detected on v3,
    mimalloc will set the MIMALLOC_MINIMAL_PURGE_SIZE to 2MiB to avoid breaking up potential THP huge pages.
    v3 uses faster TLS access on Windows, and has improved performance for mi_calloc and aligned allocations.
    Fixed rare race condition on older v3, fixed potential buffer overflow in debug statistics, add API for returning
    allocated sizes on allocation and free.

  • 2025-06-09, v1.9.4, v2.2.4, v3.1.4 (beta) : Some important bug fixes, including a case where OS memory
    was not always fully released. Improved v3 performance, build on XBox, fix build on Android, support interpose
    for older macOS versions, use MADV_FREE_REUSABLE on macOS, always check commit success, better support for Windows
    fixed TLS offset, etc.

  • 2025-03-28, v1.9.3, v2.2.3, v3.0.3 (beta) : Various small bug and build fixes, including:
    fix arm32 pre v7 builds, fix mingw build, get runtime statistics, improve statistic commit counts,
    fix execution on non BMI1 x64 systems.

  • 2025-03-06, v1.9.2, v2.2.2, v3.0.2-beta: Various small bug and build fixes.
    Add mi_options_print, mi_arenas_print, and the experimental mi_stat_get and mi_stat_get_json.
    Add mi_thread_set_in_threadpool and mi_heap_set_numa_affinity (v3 only). Add vcpkg portfile.
    Upgrade mimalloc-redirect to v1.3.2. MI_OPT_ARCH is off by default now but still assumes armv8.1-a on arm64
    for fast atomic operations. Add QNX support.

  • 2025-01-03, v1.8.9, v2.1.9, v3.0.1-alpha: Interim release. Support Windows arm64. New guarded build that can place OS
    guard pages behind objects to catch buffer overflows as they occur.
    Many small fixes: build on Windows arm64, cygwin, riscV, and dragonfly; fix Windows static library initialization to account for
    thread local destructors (in Rust/C++); macOS tag change; macOS TLS slot fix; improve stats;
    consistent mimalloc.dll on Windows (instead of mimalloc-override.dll); fix mimalloc-redirect on Win11 H2;
    add 0-byte to canary; upstream CPython fixes; reduce .bss size; allow fixed TLS slot on Windows for improved performance.

  • 2024-05-21, v1.8.7, v2.1.7: Fix build issues on less common platforms. Started upstreaming patches
    from the CPython integration. Upstream vcpkg patches.

  • 2024-05-13, v1.8.6, v2.1.6: Fix build errors on various (older) platforms. Refactored aligned allocation.

  • 2024-04-22, v1.8.4, v2.1.4: Fixes various bugs and build issues. Add MI_LIBC_MUSL cmake flag for musl builds.
    Free-ing code is refactored into a separate module (free.c). Mimalloc page info is simplified with the block size
    directly available (and new block_size_shift to improve aligned block free-ing).
    New approach to collection of abandoned segments: When
    a thread terminates the segments it owns are abandoned (containing still live objects) and these can be
    reclaimed by other threads. We no longer use a list of abandoned segments but this is now done using bitmaps in arena's
    which is more concurrent (and more aggressive). Abandoned memory can now also be reclaimed if a thread frees an object in
    an abandoned page (which can be disabled using mi_option_abandoned_reclaim_on_free). The option mi_option_max_segment_reclaim
    gives a maximum percentage of abandoned segments that can be reclaimed per try (=10%).

  • 2023-04-24, v1.8.2, v2.1.2: Fixes build issues on freeBSD, musl, and C17 (UE 5.1.1). Reduce code size/complexity
    by removing regions and segment-cache's and only use arenas with improved memory purging -- this may improve memory
    usage as well for larger services. Renamed options for consistency. Improved Valgrind and ASAN checking.

  • 2023-04-03, v1.8.1, v2.1.1: Fixes build issues on some platforms.

  • 2023-03-29, v1.8.0, v2.1.0: Improved support dynamic overriding on Windows 11. Improved tracing precision
    with asan and Valgrind, and added Windows event tracing ETW (contributed by Xinglong He). Created an OS
    abstraction layer to make it easier to port and separate platform dependent code (in src/prim). Fixed C++ STL compilation on older Microsoft C++ compilers, and various small bug fixes.

  • 2022-12-23, v1.7.9, v2.0.9: Supports building with asan and improved Valgrind support.
    Support arbitrary large alignments (in particular for std::pmr pools).
    Added C++ STL allocators attached to a specific heap (thanks @vmarkovtsev).
    Heap walks now visit all object (including huge objects). Support Windows nano server containers (by Johannes Schindelin,@dscho).
    Various small bug fixes.

  • 2022-11-03, v1.7.7, v2.0.7: Initial support for Valgrind for leak testing and heap block overflow
    detection. Initial
    support for attaching heaps to a specific memory area (only in v2). Fix realloc behavior for zero size blocks, remove restriction to integral multiple of the alignment in alloc_align, improved aligned allocation performance, reduced contention with many threads on few processors (thank you @dposluns!), vs2022 support, support pkg-config, .

  • 2022-04-14, v1.7.6, v2.0.6: fix fallback path for aligned OS allocation on Windows, improve Windows aligned allocation
    even when compiling with older SDK's, fix dynamic overriding on macOS Monterey, fix MSVC C++ dynamic overriding, fix
    warnings under Clang 14, improve performance if many OS threads are created and destroyed, fix statistics for large object
    allocations, using MIMALLOC_VERBOSE=1 has no maximum on the number of error messages, various small fixes.

  • 2022-02-14, v1.7.5, v2.0.5 (alpha): fix malloc override on
    Windows 11, fix compilation with musl, potentially reduced
    committed memory, add bin/minject for Windows,
    improved wasm support, faster aligned allocation,
    various small fixes.

  • 2021-11-14, v1.7.3, v2.0.3 (beta): improved WASM support, improved macOS support and performance (including
    M1), improved performance for v2 for large objects, Python integration improvements, more standard
    installation directories, various small fixes.

  • 2021-06-17, v1.7.2, v2.0.2 (beta): support M1, better installation layout on Linux, fix
    thread_id on Android, prefer 2-6TiB area for aligned allocation to work better on pre-windows 8, various small fixes.

  • 2021-04-06, v1.7.1, v2.0.1 (beta): fix bug in arena allocation for huge pages, improved aslr on large allocations, initial M1 support (still experimental).

  • 2021-01-31, v2.0.0: beta release 2.0: new slice algorithm for managing internal mimalloc pages.

  • 2021-01-31, v1.7.0: stable release 1.7: support explicit user provided memory regions, more precise statistics,
    improve macOS overriding, initial support for Apple M1, improved DragonFly support, faster memcpy on Windows, various small fixes.

  • 2020-09-24, v1.6.7: stable release 1.6: using standard C atomics, passing tsan testing, improved
    handling of failing to commit on Windows, add mi_process_info api call.

  • 2020-08-06, v1.6.4: stable release 1.6: improved error recovery in low-memory situations,
    support for IllumOS and Haiku, NUMA support for Vista/XP, improved NUMA detection for AMD Ryzen, ubsan support.

  • 2020-05-05, v1.6.3: stable release 1.6: improved behavior in out-of-memory situations, improved malloc zones on macOS,
    build PIC static libraries by default, add option to abort on out-of-memory, line buffered statistics.

  • 2020-04-20, v1.6.2: stable release 1.6: fix compilation on Android, MingW, Raspberry, and Conda,
    stability fix for Windows 7, fix multiple mimalloc instances in one executable, fix strnlen overload,
    fix aligned debug padding.

  • 2020-02-17, v1.6.1: stable release 1.6: minor updates (build with clang-cl, fix alignment issue for small objects).

  • 2020-02-09, v1.6.0: stable release 1.6: fixed potential memory leak, improved overriding
    and thread local support on FreeBSD, NetBSD, DragonFly, and macOSX. New byte-precise
    heap block overflow detection in debug mode (besides the double-free detection and free-list
    corruption detection). Add nodiscard attribute to most allocation functions.
    Enable MIMALLOC_PAGE_RESET by default. New reclamation strategy for abandoned heap pages
    for better memory footprint.

  • 2020-02-09, v1.5.0: stable release 1.5: improved free performance, small bug fixes.

  • 2020-01-22, v1.4.0: stable release 1.4: improved performance for delayed OS page reset,
    more eager concurrent free, addition of STL allocator, fixed potential memory leak.

  • 2020-01-15, v1.3.0: stable release 1.3: bug fixes, improved randomness and stronger
    free list encoding
    in secure mode.

  • 2019-12-22, v1.2.2: stable release 1.2: minor updates.

  • 2019-11-22, v1.2.0: stable release 1.2: bug fixes, improved secure mode (free list corruption checks, double free mitigation). Improved dynamic overriding on Windows.

  • 2019-10-07, v1.1.0: stable release 1.1.

  • 2019-09-01, v1.0.8: pre-release 8: more robust windows dynamic overriding, initial huge page support.

  • 2019-08-10, v1.0.6: pre-release 6: various performance improvements.


Overview (`bin/readme.md`)

Windows Override

We use a separate redirection DLL to override mimalloc on Windows
such that we redirect all malloc/free calls that go through the (dynamic) C runtime allocator,
including those from other DLL's or libraries. As it intercepts all allocation calls on a low level,
it can be used on large programs that include other 3rd party components.
There are four requirements to make the overriding work well:

  1. Use the C-runtime library as a DLL (using the /MD or /MDd switch).

  2. Link your program explicitly with the mimalloc.dll.lib export library for
    the mimalloc.dll -- which contains all mimalloc functionality.
    To ensure the mimalloc.dll is actually loaded at run-time it is easiest
    to insert some call to the mimalloc API in the main function, like mi_version()
    (or use the /include:mi_version switch on the linker, or
    similarly, #pragma comment(linker, "/include:mi_version") in some source file).
    See the mimalloc-test-override project for an example on how to use this.

  3. The mimalloc-redirect.dll must be put in the same folder as the main
    mimalloc.dll at runtime (as it is a dependency of that DLL).
    The redirection DLL ensures that all calls to the C runtime malloc API get
    redirected to mimalloc functions (which reside in mimalloc.dll).

  4. Ensure the mimalloc.dll comes as early as possible in the import
    list of the final executable (so it can intercept all potential allocations).
    You can use minject -l <exe> to check this if needed.

csharp
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                                                    
โ”‚ Your Program โ”‚                                                    
โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                                                    
     โ”‚                                                              
     โ”‚ mi_version()  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บโ”‚ mimalloc.dll  โ”œโ”€โ”€โ”€โ”€โ–บโ”‚ mimalloc-redirect.dll โ”‚
     โ”‚               โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
     โ”‚                      โ–ผ                                       
     โ”‚ malloc() etc. โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                               
     โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บโ”‚ ucrtbase.dll โ”‚                               
     โ”‚               โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                               
     โ”‚                                                              
     โ”‚                                                              
     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–บ ...

For best performance on Windows with C++, it
is also recommended to also override the new/delete operations (by including
mimalloc-new-delete.h
a single(!) source file in your project).

The environment variable MIMALLOC_DISABLE_REDIRECT=1 can be used to disable dynamic
overriding at run-time. Use MIMALLOC_VERBOSE=1 to check if mimalloc was successfully
redirected.

Other Platforms

You always link with mimalloc.dll but for different platforms you may
need a specific redirection DLL:

  • x64: mimalloc-redirect.dll.
  • x86: mimalloc-redirect32.dll. Use for older 32-bit Windows programs.
  • arm64: mimalloc-redirect-arm64.dll. Use for native Windows arm64 programs.
  • arm64ec: mimalloc-redirect-arm64ec.dll. The arm64ec ABI is "emulation compatible"
    mode on Windows arm64. Unfortunately we cannot run x64 code emulated on Windows arm64 with
    the x64 mimalloc override directly (since the C runtime always uses arm64ec). Instead:
    1. Build the program as normal for x64 and link as normal with the x64
      mimalloc.dll.lib export library.
    2. Now separately build mimalloc.dll in arm64ec mode and overwrite your
      previous (x64) mimalloc.dll -- the loader can handle the mix of arm64ec
      and x64 code. Now use mimalloc-redirect-arm64ec.dll to match your new
      arm64ec mimalloc.dll. The main program stays as is and can be fully x64
      or contain more arm64ec modules. At runtime, the arm64ec mimalloc.dll will
      run with native arm64 instructions while the rest of the program runs emulated x64.

Minject

We cannot always re-link an executable with mimalloc.dll, and similarly, we
cannot always ensure that the DLL comes first in the import table of the final executable.
In many cases though we can patch existing executables without any recompilation
if they are linked with the dynamic C runtime (ucrtbase.dll) -- just put the
mimalloc.dll into the import table (and put mimalloc-redirect.dll in the same
directory) Such patching can be done for example with CFF Explorer.

The minject program can also do this from the command line. Use minject --help for options:

text
> minject --help

minject:
  Injects the mimalloc dll into the import table of a 64-bit executable,
  and/or ensures that it comes first in het import table.

usage:
  > minject [options] <exe>

options:
  -h   --help        show this help
  -v   --verbose     be verbose
  -l   --list        only list imported modules
  -i   --inplace     update the exe in-place (make sure there is a backup!)
  -f   --force       always overwrite without prompting
       --postfix=<p> use <p> as a postfix to the mimalloc dll.
                     e.g. use --postfix=debug to link with mimalloc-debug.dll

notes:
  Without '--inplace' an injected <exe> is generated with the same name ending in '-mi'.
  Ensure 'mimalloc-redirect.dll' is in the same folder as the mimalloc dll.

examples:
  > minject --list myprogram.exe
  > minject --force --inplace myprogram.exe

For x86 32-bit binaries, use minject32, and for arm64 binaries use minject-arm64.


Overview (`test/readme.md`)

Testing allocators is difficult as bugs may only surface after particular
allocation patterns. The main approach to testing mimalloc is therefore
to have extensive internal invariant checking (see page_is_valid in page.c
for example), which is enabled in debug mode with -DMI_DEBUG_FULL=ON.
The main testing strategy is then to run mimalloc-bench using full
invariant checking to catch any potential problems over a wide range of intensive
allocation benchmarks and programs.

However, this does not test well for the entire API surface and this is tested
with test-api.c when using make test (from out/debug etc). (This is
not complete yet, please add to it.)

The main.c and main-override.c are there to test if building and overriding
from a local install works and therefore these build a separate test/CMakeLists.txt.


Overview (`contrib/docker/readme.md`)

Various example docker files used for testing.

Usage:

text
> cd <host>
> docker build -t <host>-mimalloc .
> docker run -it <host>-mimalloc
>> make test

Overview (`contrib/vcpkg/readme.md`)

Vcpkg support

This directory is meant to provide the sources for the official vcpkg port
of mimalloc, but can also be used to override the official port with
your own variant.

For example, you can edit the portfile.cmake
to check out a specific commit, version, or branch of mimalloc, or set further options.
You can install such custom port as:

sh
$ vcpkg install "mimalloc[override]" --recurse --overlay-ports=./contrib/vcpkg

This will also show the correct sha512 hash if you use a custom version.
Another way is to refer to the overlay from the vcpkg-configuration.json file.
See also the vcpkg documentation for more information.

Using mimalloc from vcpkg

When using cmake with vcpkg,
you can use mimalloc from the CMakeLists.txt as:

cmake
find_package(mimalloc CONFIG REQUIRED)
target_link_libraries(main PRIVATE mimalloc)

See [`test/CMakeLists.txt](../../test/CMakeLists.txt) for more examples.

Acknowledgements

The original port for vckpg was contributed by many people, including: @vicroms, @myd7349, @PhoubeHui, @LilyWangL,
@JonLiu1993, @RT2Code, Remy Tassoux, @wangao, @BillyONeal, @jiayuehua, @dg0yt, @gerar-ryan-immersaview, @nickdademo,
and @jimwang118 -- Thank you so much!


Overview (`src/prim/readme.md`)

Portability Primitives

This is the portability layer where all primitives needed from the OS are defined.

  • include/mimalloc/prim.h: primitive portability API definition.

  • prim.c: Selects one of unix/prim.c, wasi/prim.c, or windows/prim.c depending on the host platform
    (and on macOS, osx/prim.c defers to unix/prim.c).

  • include/mimalloc/prim-tls.h: primitive TLS model (thread local, pthreads, etc)

  • prim-tls.c: TLS model implementation

Note: still work in progress, there may still be places in the sources that still depend on OS ifdef's.


Overview (`src/prim/windows/readme.md`)

Primitives:

  • prim.c contains Windows primitives for OS allocation.

Event Tracing for Windows (ETW)

  • etw.h is generated from etw.man which contains the manifest for mimalloc events.
    (100 is an allocation, 101 is for a free)

  • etw-mimalloc.wprp is a profile for the Windows Performance Recorder (WPR).
    In an admin prompt, you can use:

    text
    > wpr -start src\prim\windows\etw-mimalloc.wprp -filemode
    > <my mimalloc program>
    > wpr -stop test.etl

    and then open test.etl in the Windows Performance Analyzer (WPA).


Doc Release Notes (`doc/release-notes.md`)

Binary and source releases for mimalloc.

  • v3: recommended: latest mimalloc design that tends to use less memory then v2.
  • v2: stable legacy.
  • v1: legacy.

Notes:

  • Release versions follow the v3 version (and v1 and v2 versions are incremented independently).
  • Generally it is recommended to download sources (or use vcpkg etc.) and build mimalloc as
    part of your project.
  • Source releases can also be downloaded directly from github by the tag.
    For example https://github.com/microsoft/mimalloc/archive/v3.5.1.tar.gz.
  • Binary releases include a release-, debug-, and secure build.
  • Linux binaries are built on Ubuntu 22.

--- METRICS ---