What is mimalloc?
mimalloc (pronounced “me-malloc”) is a compact, general-purpose memory allocator developed at Microsoft Research. It is designed from the ground up for high performance and low fragmentation, while remaining a strict drop-in replacement for the system malloc/free. The entire allocator is implemented in a single C file of around 6 000 lines, making it easy to audit and vendor.
mimalloc achieves its performance through free-list sharding — each memory page maintains multiple independent free lists, dramatically reducing thread contention. Pages are reused eagerly, so memory is returned to the OS quickly rather than accumulating in per-thread caches. The allocator is open source under the MIT license.
Requires libmimalloc-dev. Ubuntu/Debian: sudo apt install libmimalloc-dev
Performance Comparison
mimalloc excels at small allocations and multi-threaded workloads. The table below compares the major general-purpose allocators on typical server workloads.
| Allocator | Small Alloc Speed | Notes |
|---|---|---|
| mimalloc | ~2x faster than ptmalloc, ~1.4x faster than jemalloc | Best overall for small allocations; low fragmentation; MIT license; from Microsoft Research. |
| jemalloc | Fast; slightly behind mimalloc for small objects | Great for large arenas; most mature heap profiling tooling (jeprof); used by Firefox, Redis, Meta. |
| tcmalloc | Comparable to mimalloc | Per-thread caches from Google; slightly higher memory overhead; good profiling via pprof. |
| ptmalloc / glibc | Baseline (1x) | Default system allocator on Linux; single global lock in older versions; slowest under thread contention. |
Key Design Principles
Each memory page maintains multiple independent free lists rather than a single global one. This means threads rarely contend for the same list, enabling near-lock-free allocation in multi-threaded workloads.
Pages that become fully free are promptly returned to the OS. Unlike allocators that hold memory indefinitely in per-thread caches, mimalloc keeps resident set size low by design.
The allocator never performs an unbounded scan of free lists during allocation or deallocation. All operations have a known, predictable cost — important for latency-sensitive applications.
When moSecure is enabled, mimalloc inserts guard pages at segment boundaries, randomizes free list order, and embeds canary values to detect use-after-free and heap corruption bugs. There is a small performance cost, but the safety guarantees are strong.
Drop-in Replacement
On Linux, preload mimalloc to replace the system allocator transparently in any existing binary:
# Replace malloc/free in any binary without recompiling
LD_PRELOAD=libmimalloc.so ./myapp
# Or export it for all child processes
export LD_PRELOAD=libmimalloc.so
./myapp
No source code changes are needed for basic use. On macOS, use DYLD_INSERT_LIBRARIES. For maximum performance, link directly and use the PascalAI API below to manage custom heaps and arenas.
Types
TMIHeap
A custom heap handle (Integer). Returned by NewHeap. All allocations made from a custom heap are isolated from the default heap and from other custom heaps. Destroying a heap frees all its allocations at once — ideal for request-scoped or arena-style memory management.
TMIArena
An arena handle (Integer). Returned by NewArena. Arenas let you preallocate a large memory region and serve allocations from it, which is useful for database buffer pools, game engines, or any workload where allocation patterns are predictable.
TMIStats
A snapshot of the allocator’s internal counters, returned by GetStats. All byte fields are cumulative since program start or the last ResetStats call.
| Field | Type | Description |
|---|---|---|
| Allocated | Int64 | Bytes currently allocated and in use by the application. |
| Reserved | Int64 | Bytes reserved from the OS (may include uncommitted pages). |
| Committed | Int64 | Bytes committed (resident, mapped to physical RAM). |
| PeakAlloc | Int64 | Peak allocated bytes since program start or last reset. |
| AllocCount | Int64 | Total number of successful allocation calls. |
| FreeCount | Int64 | Total number of free calls. |
| PageCount | Int64 | Number of active memory pages currently managed. |
| SegmentCount | Int64 | Number of active segments (coarse memory regions from the OS). |
TMIOption
Enum of runtime tuning options passed to SetOption / GetOption.
| Value | Constant | Description |
|---|---|---|
| 0 | moShowErrors | Print allocator errors to stderr. |
| 1 | moShowStats | Print a stats summary to stderr on program exit. |
| 2 | moVerbose | Enable verbose diagnostic output. |
| 3 | moSecure | Enable security mitigations: guard pages, randomized free lists, canary values. |
| 6 | moArenaZero | Zero-initialize all arena allocations. |
| 9 | moLargeOSPages | Use large OS pages (hugepages, 2 MB) to reduce TLB pressure. |
| 10 | moReserveHuge | Reserve huge pages at program startup for low-latency allocation. |
| 11 | moEagerCommit | Eagerly commit pages to physical RAM on reservation. |
API Reference
Standard Allocation
Core allocation functions that replace malloc, calloc, realloc, and free. All pointer values are Int64 raw addresses.
| Function | Description |
|---|---|
| Alloc(Size) | Allocate Size bytes. Not zero-initialized. Equivalent to malloc. |
| AllocZeroed(Size) | Allocate Size bytes, zero-initialized. Equivalent to calloc(1, size). |
| AllocAligned(Size, Alignment) | Allocate with power-of-2 alignment. Use for SIMD buffers, cache-line aligned structures, or DMA transfers. |
| Realloc(Ptr, NewSize) | Resize an existing allocation. Returns a new pointer; the original Ptr is invalidated. |
| Free(Ptr) | Release memory back to the allocator. Equivalent to free. |
| AllocArray(Count, ItemSize) | Allocate a zero-initialized array of Count elements of ItemSize bytes each. Equivalent to calloc(count, itemsize). |
| AllocString(S) | Allocate a copy of string S in mimalloc memory. Equivalent to strdup. |
Custom Heaps
Custom heaps isolate a set of allocations from the default heap. Destroying a heap reclaims all its memory in a single call, which is far cheaper than freeing each pointer individually.
| Function | Description |
|---|---|
| NewHeap | Create a new isolated heap. Returns a TMIHeap handle. |
| DestroyHeap(H) | Destroy heap H and free all allocations made from it at once. |
| HeapAlloc(H, Size) | Allocate Size bytes from heap H. |
| HeapAllocZeroed(H, Size) | Allocate Size zeroed bytes from heap H. |
| HeapContains(H, Ptr) | Return True if Ptr was allocated from heap H. |
Arenas
Arenas let you manage allocation from a pre-allocated memory region. Useful for buffer pools where you control the backing memory lifetime independently of the allocations within.
| Function | Description |
|---|---|
| NewArena(Ptr, Size) | Create an arena over a pre-allocated region starting at Ptr with Size bytes. Returns a TMIArena handle. |
| FreeArena(Arena) | Release the arena handle. Does not free the underlying memory region — that is the caller’s responsibility. |
Statistics
| Function | Description |
|---|---|
| GetStats | Return a TMIStats record with current allocator counters. |
| PrintStats | Print a detailed, human-readable stats report to stderr. Useful for quick debugging without parsing structured data. |
| ResetStats | Reset all cumulative counters (AllocCount, FreeCount, PeakAlloc, etc.) to zero. |
Options
| Function | Description |
|---|---|
| SetOption(Opt, Value) | Set a TMIOption tuning parameter to Value. Call before any allocations for options that affect initialization (e.g., moLargeOSPages). |
| GetOption(Opt) | Return the current integer value of option Opt. |
Utility
| Function | Description |
|---|---|
| UsableSize(Ptr) | Return the actual usable size of the allocation at Ptr. May be larger than the originally requested size due to size-class rounding. |
| CollectFree(Force) | Eagerly release free pages back to the OS. Pass True to force immediate return; False for a best-effort collection. |
| MimallocVersion | Return the mimalloc version string. |
Code Example
Custom isolated heap for a request context
uses mimalloc;
var
RequestHeap: TMIHeap;
Buf: Int64;
Stats: TMIStats;
begin
{ Allocate from default heap }
Buf := AllocZeroed(4096);
{ ... use buffer ... }
Free(Buf);
{ Custom heap for request isolation }
RequestHeap := NewHeap;
Buf := HeapAlloc(RequestHeap, 1024);
{ ... process request ... }
DestroyHeap(RequestHeap); { frees all request allocations at once }
{ Check stats }
Stats := GetStats;
WriteLn('Peak: ' + IntToStr(Stats.PeakAlloc div 1024) + ' KB');
WriteLn('Allocs: ' + IntToStr(Stats.AllocCount));
PrintStats; { detailed report to stderr }
end.
Aligned allocation for SIMD
uses mimalloc;
{ 64-byte alignment for AVX-512 SIMD operations }
var SimdBuf := AllocAligned(4096, 64);
WriteLn('Usable: ' + IntToStr(UsableSize(SimdBuf)) + ' bytes');
{ ... SIMD work ... }
Free(SimdBuf);
{ Release free pages back to OS after a burst }
CollectFree(True);
Enabling security mitigations
SetOption(moSecure, 1) enables guard pages at segment boundaries, randomizes the order of free lists to defeat heap-spray attacks, and embeds canary values between allocations to detect use-after-free and heap corruption bugs. There is a small performance cost (typically 5–10%) but the mitigations catch entire classes of memory-safety bugs at runtime.
uses mimalloc;
{ Enable security mode before any allocations }
SetOption(moSecure, 1);
SetOption(moShowErrors, 1); { print corruption errors to stderr }
var Buf := Alloc(256);
{ use-after-free here would trigger a canary error }
Free(Buf);
{ Show allocation stats on exit }
SetOption(moShowStats, 1);
Install
libmimalloc-devPackage Info
System Requirements
libmimalloc-devUbuntu/Debian:
sudo apt install libmimalloc-dev
TMIStats Fields
.Allocated — bytes in use.Reserved — bytes from OS.Committed — resident bytes.PeakAlloc — peak usage.AllocCount — total allocs.FreeCount — total frees.PageCount — active pages.SegmentCount — active segments
Functions
- Alloc / AllocZeroed
- AllocAligned
- Realloc
- Free
- AllocArray
- AllocString
- NewHeap / DestroyHeap
- HeapAlloc / HeapAllocZeroed
- HeapContains
- NewArena / FreeArena
- GetStats / PrintStats
- ResetStats
- SetOption / GetOption
- UsableSize
- CollectFree
- MimallocVersion