Technical Documentation: microsoft/mimalloc
โน๏ธ Provenance: Multi-Tier Ingestion ยท CodeWiki Reference
Overview (`readme.md`)
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:
> LD_PRELOAD=/usr/lib/libmimalloc.so myprogramIt 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-localfreeoperations, and another one for concurrentfree
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 branchdev3). - v2: stable legacy mimalloc version. Uses thread-local segments to reduce fragmentation. (release tags:
v2.x, development branchdev2andmain) - v1: legacy version: initial design of mimalloc (release tags:
v1.x, development branchdev).
Send PR's against this version if possible (and otherwisedev3).
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 withmi_free_sizeon overaligned small allocations (#1400).2026-09-12,
v3.5.2,v2.5.2,v1.15.2: (v3) Reduced cache contention, improvedmi_malloc_csize,
improved zero'ing of small blocks,mi_wmallocvariants 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 forfreecalls.
(v3) Addedmi_free_small(_nonnull)for fast small allocations, andmi_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=FULLon 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=OFFto 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 forfree
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,
seterrnoon 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.
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 themimalloc-override-dll project builds a DLL for overriding malloc
in the entire program.
Linux, macOS, BSD, etc.
We use cmake as the build system:
> mkdir -p out/release
> cd out/release
> cmake ../..
> makeThis 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:
> mkdir -p out/debug
> cd out/debug
> cmake -DCMAKE_BUILD_TYPE=Debug ../..
> makeThis 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:
> mkdir -p out/secure
> cd out/secure
> cmake -DMI_SECURE=ON ../..
> makeThis 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:
> 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:
> cmake ..\.. -G "Visual Studio 17 2022" -A x64 -DMI_OVERRIDE=ONThe cmake build type is specified when actually building, for example:
> cmake --build . --config=ReleaseYou can also install the LLVM toolset
on Windows to build with the clang-cl compiler directly:
> cmake ../.. -G "Visual Studio 17 2022" -T ClangClSingle 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,
> gcc -o myprogram -lmimalloc myfile.cmimalloc 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:
find_package(mimalloc 1.8 REQUIRED)in your CMakeLists.txt to find a locally installed mimalloc. Then use either:
target_link_libraries(myapp PUBLIC mimalloc)to link with the shared (dynamic) library, or:
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 providesmimalloc-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):
/* 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 inNmilli-seconds (by default1000in 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. SettingNto0purges immediately when
a page becomes unused which can improve memory usage but also decreases performance.
Setting it to-1disables purging completely.MIMALLOC_PURGE_DECOMMITS=1: By default "purging" memory means unused memory is decommitted (MEM_DECOMMITon Windows,
MADV_DONTNEED(which decresease rss immediately) onmmapsystems). Set this to 0 to instead "reset" unused
memory on a purge (MEM_RESETon Windows, generallyMADV_FREE(which does not decrease rss immediately) onmmapsystems).
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 to0, 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 theMIMALLOC_MINIMAL_PURGE_SIZEin 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 mostNNUMA nodes. If not set, the actual NUMA nodes are detected
at runtime. SettingNto 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.
UseMIMALLOC_VERBOSEto 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 useMIMALLOC_RESERVE_HUGE_OS_PAGESinstead whenever possible).MIMALLOC_RESERVE_HUGE_OS_PAGES=N: whereNis 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 useMIMALLOC_ALLOW_LARGE_OS_PAGES=1in 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 useMIMALLOC_RESERVE_HUGE_OS_PAGES_AT=NwhereNis 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=FULLthere 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=1at 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 toN(by default 0). This mode places a guard page
behind everyNsuitable 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 to1to guard every object, and to0to place no guard pages at all.MIMALLOC_GUARDED_SAMPLE_SEED=N: Start sampling atN(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 (0and1GiBrespectively). If you suspect a buffer overflow occurs with an object of size
141, set the minimum and maximum to148and the sample rate to1to 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. UsingMIMALLOC_GUARDED_PRECISEplaces 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:
> 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 staticmimalloc(-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.
> env LD_PRELOAD=/usr/lib/libmimalloc.so myprogramYou can set extra environment variables to check that mimalloc is running,
like:
> env MIMALLOC_VERBOSE=1 LD_PRELOAD=/usr/lib/libmimalloc.so myprogramor run with the debug version to get detailed statistics:
> env MIMALLOC_SHOW_STATS=1 LD_PRELOAD=/usr/lib/libmimalloc-debug.so myprogramDynamic 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.
> env DYLD_INSERT_LIBRARIES=/usr/lib/libmimalloc.dylib myprogramNote 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:
Use the C-runtime library as a DLL (using the
/MDor/MDdswitch).Link your program explicitly with the
mimalloc.dll.libexport library for themimalloc.dll.
(which must be compiled with-DMI_OVERRIDE=ON, which is the default though).
To ensure themimalloc.dllis actually loaded at run-time it is easiest
to insert some call to the mimalloc API in themainfunction, likemi_version()
(or use the/include:mi_versionswitch on the linker command, or
similarly,#pragma comment(linker, "/include:mi_version")in some source file).
See themimalloc-test-overrideproject for an example on how to use this.The
mimalloc-redirect.dllmust be put in the same directory as the mainmimalloc.dllat 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 inmimalloc.dll).Ensure the
mimalloc.dllcomes as early as possible in the import
list of the final executable (so it can intercept all potential allocations).
You can useminject -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=avx2on x64 (available since 2013),-march=armv8.1on arm64 (2016),
and-march=rv64gcb_zacason 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 correspondingzalasrextension
can be enabled as-DMI_OPT_ARCH=rv64gcb_zacas_zalasrwhen 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 tomi_free. Sometimes needed when overriding malloc/free process wide.
Note also thatmi_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_zallocfor zero initialized allocations.Use the typed macros
mi_malloc_tpetc. as these are both more safe and also usemi_malloc_csizeinternally.Use
mi_malloc_csize/mi_free_csizeetc. when the allocated or free'd size is a constant as these are inlined
and statically redirect tomi_malloc_small/mi_free_smallwhen possible.
These are also used by the C++mimalloc-new-delete.hsized overrides.
You can usemi_free_csize_nonnullwhen the pointer is guaranteed to be notNULLas well.Use
mi_malloc_smallwhen the allocation size is guaranteed to be less thanMI_SMALL_SIZE_MAX(1KiB) for faster allocations.Use
mi_free_smallwhen the pointer was returned frommi_malloc_small(and guaranteed to have a
size of less thanMI_SMALL_SIZE_MAX). Usemi_free_small_nonnullwhen the pointer is guaranteed to be notNULLas 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_csizeandmi_free_csizeetc. when possible.
(or directlymi_malloc_small/mi_free_small).If the runtime already carries thread local state, it may be faster to get the default
theapfor each thread
up-front (mi_theap_get_default()) and use the bestestmi_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 theapNULLcheck. 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:
> cmake ../.. -DMI_TRACK_VALGRIND=ONThis can also be combined with secure mode or debug mode.
You can then run your programs directly under valgrind:
> 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:
> 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:
> 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:
> cmake ../.. -DMI_TRACK_ASAN=ONThis can also be combined with secure mode or debug mode.
You can then run your programs as:'
> 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:
clang -g -o test-wrong -Iinclude test/test-wrong.c out/debug/libmimalloc-asan-debug.a -lpthread -fsanitize=address -fsanitize-recover=addressSince 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 thesrc/prim/windows/etw-mimalloc.wprp profile. In an admin prompt, you can use:
> wpr -start src\prim\windows\etw-mimalloc.wprp -filemode
> <my_mimalloc_program>
> wpr -stop <my_mimalloc_program>.etland 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 ofmallocetc. 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 inmi_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 formi_heap_realloc_aligned, fixmi_(w)dupenv_sbuffer size, fix potential overflow in size options,
and error codes formi_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.
AddedMIMALLOC_ALLOW_THPoption. This is by default enabled except on Android. When THP is detected on v3,
mimalloc will set theMIMALLOC_MINIMAL_PURGE_SIZEto 2MiB to avoid breaking up potential THP huge pages.
v3 uses faster TLS access on Windows, and has improved performance formi_callocand 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.
Addmi_options_print,mi_arenas_print, and the experimentalmi_stat_getandmi_stat_get_json.
Addmi_thread_set_in_threadpoolandmi_heap_set_numa_affinity(v3 only). Add vcpkg portfile.
Upgrade mimalloc-redirect to v1.3.2.MI_OPT_ARCHis 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;
consistentmimalloc.dllon Windows (instead ofmimalloc-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. Upstreamvcpkgpatches.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. AddMI_LIBC_MUSLcmake 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 newblock_size_shiftto 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 usingmi_option_abandoned_reclaim_on_free). The optionmi_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 (insrc/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 forstd::pmrpools).
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). Fixreallocbehavior for zero size blocks, remove restriction to integral multiple of the alignment inalloc_align, improved aligned allocation performance, reduced contention with many threads on few processors (thank you @dposluns!), vs2022 support, supportpkg-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, addbin/minjectfor 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, addmi_process_infoapi 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, fixstrnlenoverload,
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). Addnodiscardattribute to most allocation functions.
EnableMIMALLOC_PAGE_RESETby 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:
Use the C-runtime library as a DLL (using the
/MDor/MDdswitch).Link your program explicitly with the
mimalloc.dll.libexport library for
themimalloc.dll-- which contains all mimalloc functionality.
To ensure themimalloc.dllis actually loaded at run-time it is easiest
to insert some call to the mimalloc API in themainfunction, likemi_version()
(or use the/include:mi_versionswitch on the linker, or
similarly,#pragma comment(linker, "/include:mi_version")in some source file).
See themimalloc-test-overrideproject for an example on how to use this.The
mimalloc-redirect.dllmust be put in the same folder as the mainmimalloc.dllat 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 inmimalloc.dll).Ensure the
mimalloc.dllcomes as early as possible in the import
list of the final executable (so it can intercept all potential allocations).
You can useminject -l <exe>to check this if needed.
โโโโโโโโโโโโโโโโ
โ 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 includingmimalloc-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 usesarm64ec). Instead:- Build the program as normal for x64 and link as normal with the x64
mimalloc.dll.libexport library. - Now separately build
mimalloc.dllinarm64ecmode and overwrite your
previous (x64)mimalloc.dll-- the loader can handle the mix of arm64ec
and x64 code. Now usemimalloc-redirect-arm64ec.dllto match your new
arm64ecmimalloc.dll. The main program stays as is and can be fully x64
or contain more arm64ec modules. At runtime, the arm64ecmimalloc.dllwill
run with native arm64 instructions while the rest of the program runs emulated x64.
- Build the program as normal for x64 and link as normal with the 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 themimalloc.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:
> 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.exeFor 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:
> cd <host>
> docker build -t <host>-mimalloc .
> docker run -it <host>-mimalloc
>> make testOverview (`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:
$ vcpkg install "mimalloc[override]" --recurse --overlay-ports=./contrib/vcpkgThis 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:
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 ofunix/prim.c,wasi/prim.c, orwindows/prim.cdepending on the host platform
(and on macOS,osx/prim.cdefers tounix/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.ccontains Windows primitives for OS allocation.
Event Tracing for Windows (ETW)
etw.his generated frometw.manwhich contains the manifest for mimalloc events.
(100 is an allocation, 101 is for a free)etw-mimalloc.wprpis 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.etland then open
test.etlin 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
vcpkgetc.) 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 ---
- Files Extracted: 8
- Estimated Token Budget: ~17739 tokens
- Canonical Reference: https://codewiki.google/github.com/microsoft/mimalloc