mimalloc is a compact general purpose allocator with excellent performance.

Overview

mimalloc

 

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

Latest release tag: v2.0.0 (beta, 2021-01-31).
Latest stable tag: v1.7.0 (2021-01-31).

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/bin/libmimalloc.so  myprogram

It also has an easy way to override the default allocator in Windows. Notable aspects of the design include:

  • small and consistent: the library is about 8k 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).
  • 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 reset: when a "page" becomes empty (with increased chance due to free list sharding) the memory is marked to the OS as unused ("reset" or "purged") 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.
  • bounded: it does not suffer from blowup [1], has bounded worst-case allocation times (wcat), bounded space overhead (~0.2% meta-data, with at most 12.5% waste in allocation sizes), 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!

Branches

  • master: latest stable release.
  • dev: development branch for mimalloc v1.
  • dev-slice: development branch for mimalloc v2 with a new algorithm for managing internal mimalloc pages.

Release

  • 2021-01-31, v2.0.0: beta release 2.0: new algorithm for managing internal mimalloc pages that tends to use reduce memory usage and fragmentation compared to mimalloc v1 (especially for large workloads). Should otherwise have similar performance (see below); please report if you observe any significant performance regression.

  • 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.

Older Releases

  • 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.

Special thanks to:

  • 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.

Usage

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

Building

Windows

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

macOS, Linux, BSD, etc.

We use cmake1 as the build system:

> 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:

> 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:

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

This will name the shared library as libmimalloc-secure.so. Use ccmake2 instead of cmake to see and customize all the available build options.

Notes:

  1. Install CMake: sudo apt-get install cmake
  2. Install CCMake: sudo apt-get install cmake-curses-gui

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.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:

find_package(mimalloc 1.4 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 convience, 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):

> env MIMALLOC_SHOW_STATS=1 ./cfrac 175451865205073170563711388363

175451865205073170563711388363 = 374456281610909315237213 * 468551

heap stats:     peak      total      freed       unit
normal   2:    16.4 kb    17.5 mb    17.5 mb      16 b   ok
normal   3:    16.3 kb    15.2 mb    15.2 mb      24 b   ok
normal   4:      64 b      4.6 kb     4.6 kb      32 b   ok
normal   5:      80 b    118.4 kb   118.4 kb      40 b   ok
normal   6:      48 b       48 b       48 b       48 b   ok
normal  17:     960 b      960 b      960 b      320 b   ok

heap stats:     peak      total      freed       unit
    normal:    33.9 kb    32.8 mb    32.8 mb       1 b   ok
      huge:       0 b        0 b        0 b        1 b   ok
     total:    33.9 kb    32.8 mb    32.8 mb       1 b   ok
malloc requested:         32.8 mb

 committed:    58.2 kb    58.2 kb    58.2 kb       1 b   ok
  reserved:     2.0 mb     2.0 mb     2.0 mb       1 b   ok
     reset:       0 b        0 b        0 b        1 b   ok
  segments:       1          1          1
-abandoned:       0
     pages:       6          6          6
-abandoned:       0
     mmaps:       3
 mmap fast:       0
 mmap slow:       1
   threads:       0
   elapsed:     2.022s
   process: user: 1.781s, system: 0.016s, faults: 756, reclaims: 0, rss: 2.7 mb

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.
  • MIMALLOC_SHOW_ERRORS=1: show error and warning messages.
  • MIMALLOC_PAGE_RESET=0: by default, mimalloc will reset (or purge) OS pages that are not in use, to signal to the OS that the underlying physical memory can be reused. This can reduce memory fragmentation in long running (server) programs. By setting it to 0 this will no longer be done which can improve performance for batch-like programs. As an alternative, the MIMALLOC_RESET_DELAY= can be set higher (100ms by default) to make the page reset occur less frequently instead of turning it off completely.
  • 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_LARGE_OS_PAGES=1: use large OS pages (2MiB) when available; for some workloads this can significantly improve performance. Use MIMALLOC_VERBOSE to check if the large OS pages are enabled -- usually one needs to explicitly allow 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_LARGE_OS_PAGES 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 enable huge OS pages (as on Windows and Linux)). With huge OS pages, it may be beneficial to set the setting MIMALLOC_EAGER_COMMIT_DELAY=N (N is 1 by default) to delay the initial N segments (of 4MiB) of a thread to not allocate in the huge OS pages; this prevents threads that are short lived and allocate just a little to take up space in the huge OS page area (which cannot be reset).

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 big 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 pages are surrounded by guard pages and the heap metadata is behind a guard page as well (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.

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, 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.

Overriding Malloc

Overriding the standard malloc can be done either dynamically or statically.

Dynamic override

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

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 myprogram

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

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

or run with the debug version to get detailed statistics:

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

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_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=/usr/lib/libmimalloc.dylib myprogram

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

(Note: macOS support for dynamic overriding is recent, please report any issues.)

Override on Windows

Overriding on Windows is robust and has the particular advantage to be able to redirect all malloc/free calls that go through the (dynamic) C runtime allocator, including those from other DLL's or libraries.

The overriding on Windows requires that you link your program explicitly with the mimalloc DLL and use the C-runtime library as a DLL (using the /MD or /MDd switch). Also, the mimalloc-redirect.dll (or mimalloc-redirect32.dll) must be available in the same folder as the main mimalloc-override.dll at runtime (as it is a dependency). The redirection DLL ensures that all calls to the C runtime malloc API get redirected to mimalloc (in mimalloc-override.dll).

To ensure the mimalloc DLL is 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). See the mimalloc-override-test project for an example on how to use this. 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.

(Note: in principle, it is possible to even patch existing executables without any recompilation if they are linked with the dynamic C runtime (ucrtbase.dll) -- just put the mimalloc-override.dll into the import table (and put mimalloc-redirect.dll in the same folder) Such patching can be done for example with CFF Explorer).

Static override

On Unix-like systems, you can also 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-override.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-override.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!

Performance

Last update: 2021-01-30

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 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.

Comments
  • Segmantation fault for very big data on 32-bit linux build

    Segmantation fault for very big data on 32-bit linux build

    I have segmentation error only for Release build, when I tired to work with very big data (about 1GB arrays) on 32 bit linux os (mimalloc 1.6.1). I build app with additional debug info, and there is next core dump:

    received signal SIGSEGV, Segmentation fault. [Switching to Thread 0xe358bb40 (LWP 16919)] mi_segment_init (segment=0x94400000, [email protected]=0x0, [email protected]=0, [email protected]=MI_PAGE_SMALL, page_shift=15, tld=0xd856b644, os_tld=0xd856b684) at /home/sies_unit/.conan/data/mimalloc/1.6.1/sies/testing/build/a98ffa6b232ae76f738ec2524a9fc9ba058249ac/source_subfolder/src/segment.c:635 635 /home/sies_unit/.conan/data/mimalloc/1.6.1/sies/testing/build/a98ffa6b232ae76f738ec2524a9fc9ba058249ac/source_subfolder/src/segment.c: Нет такого файла или каталога. (gdb) bt -full #0 mi_segment_init (segment=0x94400000, [email protected]=0x0, [email protected]=0, [email protected]=MI_PAGE_SMALL, page_shift=15, tld=0xd856b644, os_tld=0xd856b684) at /home/my_app/.conan/data/mimalloc/1.6.1/project/testing/build/a98ffa6b232ae76f738ec2524a9fc9ba058249ac/source_subfolder/src/segment.c:635 memid = 1088 mem_large = false capacity = 64 info_size = 4096 pre_size = 8192 segment_size = <optimized out> eager_delayed = <optimized out> eager = <optimized out> commit = true pages_still_good = false is_zero = true #1 0xf7fb10b2 in mi_segment_alloc (os_tld=0xd856b684, tld=0xd856b644, page_shift=15, page_kind=MI_PAGE_SMALL, required=0) at /home/my_app/.conan/data/mimalloc/1.6.1/project/testing/build/a98ffa6b232ae76f738ec2524a9fc9ba058249ac/source_subfolder/src/segment.c:682 No locals. #2 mi_segment_reclaim_or_alloc (heap=0xd856b000, block_size=8192, page_kind=MI_PAGE_SMALL, page_shift=15, tld=<optimized out>, os_tld=0xd856b684) at /home/my_app/.conan/data/mimalloc/1.6.1/project/testing/build/a98ffa6b232ae76f738ec2524a9fc9ba058249ac/source_subfolder/src/segment.c:1201 segment = 0x0 reclaimed = false page_shift = 15 heap = 0xd856b000 os_tld = 0xd856b684 tld = 0xd856b644 page_kind = MI_PAGE_SMALL block_size = 8192 segment = 0x0 reclaimed = <optimized out> #3 0xf7fb12ff in mi_segment_page_alloc ([email protected]=0xd856b000, [email protected]=8192, [email protected]=MI_PAGE_SMALL, page_shift=15, tld=0xd856b644, os_tld=0xd856b684) at /home/my_app/.conan/data/mimalloc/1.6.1/project/testing/build/a98ffa6b232ae76f738ec2524a9fc9ba058249ac/source_subfolder/src/segment.c:1234 segment = <optimized out> free_queue = <optimized out> page = <optimized out> #4 0xf7fb1745 in mi_segment_small_page_alloc (os_tld=0xd856b684, tld=0xd856b644, block_size=8192, heap=0xd856b000) at /home/my_app/.conan/data/mimalloc/1.6.1/project/testing/build/a98ffa6b232ae76f738ec2524a9fc9ba058249ac/source_subfolder/src/segment.c:1251 No locals. #5 _mi_segment_page_alloc (heap=0xd856b000, block_size=8192, tld=0xd856b644, os_tld=0xd856b684) at /home/my_app/.conan/data/mimalloc/1.6.1/project/testing/build/a98ffa6b232ae76f738ec2524a9fc9ba058249ac/source_subfolder/src/segment.c:1321 page = <optimized out> #6 0xf7fb1c1b in mi_page_fresh_alloc ([email protected]=0xd856b000, [email protected]=0xd856b3e8, block_size=8192) at /home/my_app/.conan/data/mimalloc/1.6.1/project/testing/build/a98ffa6b232ae76f738ec2524a9fc9ba058249ac/source_subfolder/src/page.c:247 page = <optimized out> #7 0xf7fb31ca in mi_page_fresh (pq=0xd856b3e8, heap=0xd856b000) at /home/my_app/.conan/data/mimalloc/1.6.1/project/testing/build/a98ffa6b232ae76f738ec2524a9fc9ba058249ac/source_subfolder/src/page.c:264 page = <optimized out> page = <optimized out> #8 mi_page_queue_find_free_ex (heap=0xd856b000, pq=0xd856b3e8, first_try=<optimized out>) at /home/my_app/.conan/data/mimalloc/1.6.1/project/testing/build/a98ffa6b232ae76f738ec2524a9fc9ba058249ac/source_subfolder/src/page.c:679 count = <optimized out> page = 0x0 #9 0xf7fb33c2 in mi_find_free_page (size=8192, heap=0xd856b000) at /home/my_app/.conan/data/mimalloc/1.6.1/project/testing/build/a98ffa6b232ae76f738ec2524a9fc9ba058249ac/source_subfolder/src/page.c:713 pq = 0xd856b3e8 page = 0x9f400c0c pq = <optimized out>

    As you can see, the problem, that allocated segment pointer referenced to corrupted data. In Debug build there is no problem, therefore, I think, that problem in padding of allocated memory.

    I tried to locolize problem, but still cann't to do it. From other side, I cann't share my production code.

    I will continue try to catch this problem by unit test, but hope, this information will provide any ideas about this segmentation.

    Thank you for attention!

    opened by synacker 34
  • use libmimalloc.so ,segmentfault error always occured when i free heap-data

    use libmimalloc.so ,segmentfault error always occured when i free heap-data

    i use libmimalloc.so.1.7 in a complex project with threadpool(over 20 thread),and the device is aarch64-linux-gnu, gcc is 6.2.1。 i try to use gdb to debug, the bt is '

    Thread 22 "Other" received signal SIGSEGV, Segmentation fault. [Switching to Thread 0xffff51969170 (LWP 1603)] mi_free_generic (segment=0xffff34000000, local=false, p=0xffff34000940) at mimalloc-master/src/alloc.c:440 (gdb) bt #0 mi_free_generic (segment=0xffff34000000, local=false, p=0xffff34000940) at mimalloc-master/src/alloc.c:440

    i try to print ags and local vals, as :

    (gdb) p p $1 = (void *) 0xffff34000940 (gdb) p *p Attempt to dereference a generic pointer. (gdb) p segment $2 = {memid = 281471554158624, mem_is_pinned = false, mem_is_committed = false, abandoned_next = 0x21000, next = 0x21000, prev = 0x300000000, abandoned = 0, abandoned_visits = 0, used = 0, capacity = 0, segment_size = 0, segment_info_size = 0, cookie = 0, page_shift = 0, thread_id = 0, page_kind = MI_PAGE_SMALL, pages = {{ segment_idx = 224 '\340', segment_in_use = 1 '\001', is_reset = 1 '\001', is_committed = 1 '\001', is_zero_init = 1 '\001', capacity = 13312, reserved = 65535, flags = {full_aligned = 0 '\000', x = { in_full = 0 '\000', has_aligned = 0 '\000'}}, is_zero = 0 '\000', retire_expire = 0 '\000', free = 0x0, used = 872415352, xblock_size = 65535, local_free = 0xffff34000078, xthread_free = 281471554158728, xheap = 281471554158728, next = 0xffff34000098, prev = 0xffff34000098}}} (gdb) p (mi_block_t)p $3 = (mi_block_t *) 0xffff34000940

    i dont know why it always trigger segmentfault, who can give me some useful info

    opened by DavidWzh 33
  •  Play nice with thread sanitizer

    Play nice with thread sanitizer

    Currently, if you build mimalloc with thread sanitizer you'll get data race warnings. Here's an example program that allocates that frees blocks concurrently from multiple threads:

    https://gist.github.com/colesbury/7637424c7367981eb13c7bd18be2fb09

    (Note that t1 and t2 are freeing different blocks, but the blocks share the same page)

    One of the reported data races is here:

    https://github.com/microsoft/mimalloc/blob/cbc826beb598f48099a3b35d6f228103a630085a/src/alloc.c#L116-L130

    The (volatile but non-atomic) read of page->thread_free races with the atomic compare-and-swap. The compiled code is probably fine as-is, but it'd be nice to use thread sanitizer with mimalloc. I suspect the required changes are relatively small.

    I noticed the dev-exp branch has mi_atomic_read and mi_atomic_write, but these don't seem to be used in alloc.c yet.

    opened by colesbury 28
  • C++11 conforming STL allocator

    C++11 conforming STL allocator

    • allocate() now throws on error
    • Class is trivially default constructible
    • Explicitly require C++11 or later because C++98 allocator requirements aren't satisfied anyways
    opened by viccpp 25
  • Application which uses many dlls crashes when using mimalloc under Windows

    Application which uses many dlls crashes when using mimalloc under Windows

    Hello,

    our application crashes when it uses mimalloc-override. The application uses many dlls. The crash occurrs when memory within the CRT is freed. Here ist the stacktrace:

    ntdll.dll!string "Enabling heap debug options\n"()	Unbekannt
    ntdll.dll!RtlValidateHeap()	Unbekannt
    AcXtrnal.dll!000007febd077bac()	Unbekannt
    ucrtbase.dll!__acrt_free_locale()	Unbekannt
    ucrtbase.dll!_updatetlocinfoEx_nolock()	Unbekannt
    ucrtbase.dll!_updatetlocinfoEx_nolock()	Unbekannt
    ucrtbase.dll!__crt_seh_guarded_call<void>::operator()<class <lambda_d67e8342c384adda8f857579ab50b2ae>,class <lambda_30712929f77e709619002f448b6a9510> &,class <lambda_4525336fd7e478d965fb7ca7a337cad8> >(class <lambda_d67e8342c384adda8f857579ab50b2ae> &&,class <lambda_30712929f77e709619002f448b6a9510> &,class <lambda_4525336fd7e478d965fb7ca7a337cad8> &&)	Unbekannt
    ucrtbase.dll!_wcscats()	Unbekannt
    ucrtbase.dll!__crt_seh_guarded_call<void>::operator()<class <lambda_5df02c53a8f32f81fd64e5bbb78039f1>,class <lambda_2af78c5f5901b1372d98f9ab3177dfa6> &,class <lambda_f51fe5fd7c79a33db34fc9310f277369> &>(class <lambda_5df02c53a8f32f81fd64e5bbb78039f1> &&,class <lambda_2af78c5f5901b1372d98f9ab3177dfa6> &,class <lambda_f51fe5fd7c79a33db34fc9310f277369> &)	Unbekannt
    ucrtbase.dll!_wsetlocale()	Unbekannt
    ucrtbase.dll!___lc_locale_name_func()	Unbekannt
    ucrtbase.dll!setlocale()	Unbekannt
    msvcp140.dll!000007fee58c1724()	Unbekannt
    msvcp140.dll!000007fee58b46a4()	Unbekannt
    msvcp140.dll!000007fee58b5e59()	Unbekannt
    

    dlltools.dll!std::use_facet<std::codecvt<char,char,_Mbstatet>>(const std::locale & _Loc) Zeile 519 C++ [Inlineframe] dlltools.dll!std::basic_filebuf<char,std::char_traits>::open(const char *) Zeile 292 C++ [Inlineframe] dlltools.dll!std::basic_fstream<char,std::char_traits>::{ctor}(const char *) Zeile 1328 C++ dlltools.dll!C_ConfigFile::CheckForNewLineOnLastLine() Zeile 904 C++ dlltools.dll!C_ConfigFile::SetLockName() Zeile 159 C++ dlltools.dll!C_ConfigFile::SetConfigFileName(const std::string & strName) Zeile 883 C++ dlltools.dll!C_ZISDirectories::ReadConfigFile() Zeile 785 C++ dlltools.dll!C_ZISDirectories::Init_Impl() Zeile 418 C++ dlltools.dll!C_ZISDirectories::C_ZISDirectories() Zeile 70 C++ dlltools.dll!C_ZISDirectories::instance(const char * pszBinDirectory) Zeile 57 C++ dllunittestutilities.dll!C_ConsoleModus::ActivateLocalMiniDump_Impl() Zeile 223 C++ dllunittestutilities.dll!C_ConsoleModus::Execute(int argc, char * * argv, const std::string & strXMLFileName) Zeile 53 C++ dbgtools.exe!ace_main_i(int argc, char * * argv) Zeile 347 C++ dbgtools.exe!main(int argc, char * * argv) Zeile 181 C++

    This is the executed code in "dlltools.dll!C_ConfigFile::CheckForNewLineOnLastLine() Zeile 904":

    std::fstream myFile(strConfigFileName.c_str(), std::ios::in | std::ios::out); if(myFile.is_open()) ...

    The application crashes in "Debug" and in "Release" mode. When the application starts in "Debug" mode the following message is printed to stdout: "mimalloc-redirect: warning: unable to resolve "ucrtbase.DLL!_msize_base" -- this may cause allocation errors." In the "Release" mode no message is printed to stdout.

    The same code works fine when it is executed within the test application mimalloc-override-test.exe.

    int main() { //mi_stats_reset(); // ignore earlier allocations atexit(free_p); void* p1 = malloc(78); void* p2 = mi_malloc_aligned(16,24); free(p1);
    p1 = malloc(8); char* s = mi_strdup("hello\n"); _putenv("TEST=ENV");

    int twice = 0; do { printf("Locale is: %s\n", setlocale(LC_ALL, NULL)); std::fstream myfile("example.txt", std::ios::in | std::ios::out); if(myfile.is_open()) { myfile << "This is a line.\n"; myfile << "This is another line.\n"; myfile.close(); } setlocale(LC_ALL, ""); } while(!twice++); ... }

    Best regards Michael

    opened by migra-leutek 21
  • Building with mingw: os.c build failure

    Building with mingw: os.c build failure

    Maybe my question doesn't belong in an issue, in which case I really apologize.

    I would like to build the mimalloc library on Windows, without Visual Studio. I use GCC and Make to build my projects.

    I have configured the CMake (where I so specified the compilers to use) to compile according to these preferences and it seems to work fine.

    However, I have a compilation problem when building os.c, as shown in the given picture, PROCESSOR_NUMBER (and the functions that follow) don't seem to be found or exist. Nevertheless, some fixes to the MinGW version seem to have already been made 🤔

    img

    I'm not used to using Windows headers, and I haven't found anything on the Internet that can help me overcome this problem of build. I don't know where to find what is missing. What should I change in my configurations? Or don't I have all the necessary files?

    I would really like to test mimalloc, which looks really well designed, thanks :)

    help wanted 
    opened by vanaur 20
  • SegFault when freeing on a different thread > 2 MB

    SegFault when freeing on a different thread > 2 MB

    This test fails (using C# P/Invoke).

    [Test, Explicit]
    public void CouldFreeOnDifferentThread()
    {
        var length = 2 * 1024 * 1024 + 1; // fails > 2MB
        for (int i = 0; i < 100; i++)
        {
            var pm = Mem.Malloc((UIntPtr) (length));
            // Mem.Free(pm); // works
            Task.Run(() =>
            {
                Mem.Free(pm); // fails
            }).Wait();
        }
    }
    

    This escaped my original testing due to small buffers, but same behavior with real threads, not tasks:

    [Test]
    public void CouldAllocFreeFromDifferentThreads()
    {
        var bc = new BlockingCollection<IntPtr>();
        var are = new AutoResetEvent(false);
        var count = 100;
        var t1 = new Thread(() =>
        {
            for (int i = 0; i < count; i++)
            {
                var ptr = Mem.MallocAligned((UIntPtr) (2 * 1024 * 1024 + 1), (UIntPtr) (8));
                bc.Add((IntPtr) ptr);
                are.WaitOne();
            }
    
            bc.CompleteAdding();
        });
        t1.Start();
    
        var t2 = new Thread(() =>
        {
            foreach (var intPtr in bc.GetConsumingEnumerable())
            {
                Mem.Free((byte*) intPtr);
                are.Set();
            }
        });
        t2.Start();
        t1.Join();
        t2.Join();
    }
    

    I'm still using 1.6.1 release, haven't yet recompiled for #212.

    opened by buybackoff 19
  • Crash on Firefox start with mimalloc being ld.so.preload'ed

    Crash on Firefox start with mimalloc being ld.so.preload'ed

    firefox[7891]: segfault at 28 ip 00007f40c0d8bfa0 sp 00007ffed98afff8 error 4 in libpthread-2.27.so[7f40c0d82000+1a000]

    version: 06f8da4218a6e86f0418e249a99faa9957c2ec5f

    Description: Ubuntu 18.04.2 LTS GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1) stable release version 2.27.

    opened by poige 19
  • Better memcpy on Windows

    Better memcpy on Windows

    The following code:

    // dst and src must be 16-byte aligned
    // size must be multiple of 16*2 = 32 bytes
    inline void memcpy_sse ( void * dst, void const * src, size_t size ) {
    // https://hero.handmade.network/forums/code-discussion/t/157-memory_bandwidth_+_implementing_memcpy
        size_t stride = 2 * sizeof ( __m128 );
        while ( size ) {
            __m128 a = _mm_load_ps ( ( float * ) ( ( uint8_t const * ) src ) + 0 * sizeof ( __m128 ) ) );
            __m128 b = _mm_load_ps ( ( float * ) ( ( ( uint8_t const * ) src ) + 1 * sizeof ( __m128 ) ) );
            _mm_stream_ps ( ( float * ) ( ( ( uint8_t * ) dst ) + 0 * sizeof ( __m128 ) ), a );
            _mm_stream_ps ( ( float * ) ( ( ( uint8_t * ) dst ) + 1 * sizeof ( __m128 ) ), b );
            size -= stride;
            src = ( ( uint8_t const * ) src ) + stride;
            dst = ( ( uint8_t * ) dst ) + stride;
        }
    }
    

    is a SSE2-streaming-coded memcpy, it's about 25% faster than memcpy on Windows. The AVX-streaming version is not faster than the SSE2 version, so better use SSE2 for lower size and easier alignment constraints and almost any (PC-)processor, still functioning, supports it. Speed up for grabs.

    PS: mimalloc uses memcpy 15 times in dev (I grepped it, so you don't have to grep it, I didn't look whether it would be applicable in every single case).

    opened by degski 18
  • Setup Github Releases

    Setup Github Releases

    When pulling in sources to build and package this library, the ideal case is for the library authors to use Github releases with periodic versioned releases. Currently we're pulling from Master and pinning to commits, but that is sub-optimal. It doesn't even need to be a 1.0 release, it could be some 0.1.0 pre-release.

    opened by solvingj 18
  • Some performance issues with mimalloc

    Some performance issues with mimalloc

    Hi, I tried mimalloc in ClickHouse and faced some (I hope so) interesting issues.

    The slowdown against default jemalloc was big -- the query processing is approximately two times slower than usual.

    I looked around and have some questions with examples of why something is happening.

    First of all, everything is done under Linux x86-64.

    The example

    #include <memory>
    
    int main() {
        std::unique_ptr<int[]> a(new int[1ull << 30]);
        return 0;
    }
    

    With standard allocator, I have only 1 mmap and 1 munmap which is pretty cool and expected because allocation is huge.

    strace -fe mmap,munmap ./test
    ...
    mmap(NULL, 4294971392, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f5c63616000
    munmap(0x7f5c63616000, 4294971392)      = 0
    

    With mimalloc, I have 6 mmaps and munmaps with rather big ones that are doubled.

    mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8f24999000
    mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8f24996000
    munmap(0x7f8f24e71000, 193620)          = 0
    mmap(NULL, 4194304, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8f24596000
    munmap(0x7f8f24596000, 4194304)         = 0
    mmap(NULL, 8388608, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8f24196000
    munmap(0x7f8f24196000, 2531328)         = 0
    munmap(0x7f8f24800000, 1662976)         = 0
    mmap(NULL, 4294967504, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8e243ff000
    munmap(0x7f8e243ff000, 4294967504)      = 0
    mmap(NULL, 4299161808, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f8e23fff000
    munmap(0x7f8e23fff000, 4096)            = 0
    munmap(0x7f8f24001000, 4186320)         = 0
    munmap(0x7f8e24000000, 4294967504)      = 0
    

    Then I read some code and saw the https://github.com/microsoft/mimalloc/blob/master/src/segment.c#L290 and https://github.com/microsoft/mimalloc/blob/master/src/os.c#L284 that wants 4mb alignment and it is highly unlikely for Linux to have such address after mmap syscall. So we do munmap once, then use the slow method to mmap once and munmap two times more because we don't want to store mmap useless regions https://github.com/microsoft/mimalloc/blob/master/src/os.c#L245. I am not sure this behavior is somehow optimal (at least with Linux we should not wait for 4mb alignment after mmap).

    And is there any deallocated regions reuse? Because I tried such code below and saw a lot of mmap and munmap calls (for each construction and destruction many times).

    #include <memory>
    #include <thread>
    #include <vector>
    
    void Foo() {
        for (size_t i = 0; i < 10000; ++i) {
            std::unique_ptr<int[]> a(new int[1ull << 18]);
        }
    }
    
    int main() {
        std::vector<std::thread> thrs;
        for (size_t i = 0; i < 10; ++i) {
            thrs.emplace_back(Foo);
        }
        for (auto&& thr : thrs) {
            thr.join();
        }
        return 0;
    }
    

    With jemalloc and default allocator such code works almost immediately

    time ./test                                                     
    ./test  0.02s user 0.00s system 205% cpu 0.011 total
    

    With mimalloc it is extremely slow

    time LD_PRELOAD=mimalloc/build/libmimalloc.so ./test
    LD_PRELOAD=mimalloc/build/libmimalloc.so ./test  0.42s user 4.62s system 164% cpu 3.055 total
    

    And such usage of the allocator is common, for example, in server applications, when you accept the query, process it and then again accept the query, memory reuse can help to avoid syscall penalty.

    So the question is -- what are the best practices of using mimalloc? :)

    opened by danlark1 17
  • Can't install on Haiku R1 beta 4

    Can't install on Haiku R1 beta 4

    mimalloc builds just fine, but it appears that there's something wrong with the default install path. Or am I doing something wrong?

    ~/mimalloc/build> make install
    [ 40%] Built target mimalloc
    [ 81%] Built target mimalloc-static
    [ 83%] Built target mimalloc-obj
    [ 89%] Built target mimalloc-test-api
    [ 94%] Built target mimalloc-test-api-fill
    [100%] Built target mimalloc-test-stress
    Install the project...
    -- Install configuration: "Release"
    -- Installing: /boot/system/lib/libmimalloc.so.2.0
    CMake Error at cmake_install.cmake:52 (file):
      file INSTALL cannot copy file
      "/boot/home/mimalloc/build/libmimalloc.so.2.0" to
      "/boot/system/lib/libmimalloc.so.2.0": Read-only file system.
    
    opened by realtaraharris 2
  • mimalloc slower than default macOS allocator

    mimalloc slower than default macOS allocator

    While looking at crystal-lang/crystal#12879, I noticed mimalloc (2.0.9) is quite a bit slower than the default macOS allocator:

    $ command time -l env DYLD_INSERT_LIBRARIES=/opt/local/lib/libmimalloc.dylib crystal build src/ktistec/server.cr 
           87.03 real        58.90 user        27.26 sys
              2632253440  maximum resident set size
                       0  average shared memory size
                       0  average unshared data size
                       0  average unshared stack size
                 4960241  page reclaims
                   19511  page faults
                       0  swaps
                       0  block input operations
                       0  block output operations
                       0  messages sent
                       0  messages received
                    1198  signals received
                    3384  voluntary context switches
                  258169  involuntary context switches
            125973599945  instructions retired
            122164295133  cycles elapsed
              2652803072  peak memory footprint
    
    command time -l env crystal build src/ktistec/server.cr 
           65.25 real        45.84 user        19.13 sys
              2542522368  maximum resident set size
                       0  average shared memory size
                       0  average unshared data size
                       0  average unshared stack size
                 3163809  page reclaims
                   17493  page faults
                       0  swaps
                       0  block input operations
                       0  block output operations
                       0  messages sent
                       0  messages received
                    1200  signals received
                    2977  voluntary context switches
                  178920  involuntary context switches
            128321914720  instructions retired
            122676736235  cycles elapsed
              2686603264  peak memory footprint
    

    For some background information, Crystal is a compiler with an LLVM backend. The project I'm building is available here and Crystal can be installed via Homebrew/MacPorts under the name crystal (run shards install in the project directory once).

    opened by mohd-akram 0
  • _mi_stats_main.committed.current does goes out of sync with real RSS usage

    _mi_stats_main.committed.current does goes out of sync with real RSS usage

    When tracking _mi_stats_main.committed.current I would expect that it won't go bigger than VmRSS in /proc/../status.

    In practice, I see that for a long running process, I get:

    comitted_memory:98553561088
    used_memory_rss:89664389120
    

    which does not make sense to me. We regularly run mi_stats_merge() from all the threads to combine the stats into _mi_stats_main.

    Aggregating data from mi_heap_visit_blocks(heap, false, ..) over all threads provides accurate information about committed memory. It is similar to what I would expect to see (close to used_memory_rss).

    opened by romange 4
Owner
Microsoft
Open source projects and samples from Microsoft
Microsoft
STL compatible C++ memory allocator library using a new RawAllocator concept that is similar to an Allocator but easier to use and write.

STL compatible C++ memory allocator library using a new RawAllocator concept that is similar to an Allocator but easier to use and write.

Jonathan Müller 1k Dec 2, 2021
The Best and Highest-Leveled and Newest bingding for MiMalloc Ever Existed in Rust

The Best and Highest-Leveled and Newest bingding for MiMalloc Ever Existed in Rust mimalloc 1.7.2 stable Why create this in repo https://github.com/pu

LemonHX 31 Dec 17, 2022
Mimalloc-bench - Suite for benchmarking malloc implementations.

Mimalloc-bench Suite for benchmarking malloc implementations, originally developed for benchmarking mimalloc. Collection of various benchmarks from th

Daan 186 Dec 24, 2022
jemalloc websitejemalloc - General purpose malloc(3) implementation that emphasizes fragmentation avoidance and scalable concurrency support. [BSD] website

jemalloc is a general purpose malloc(3) implementation that emphasizes fragmentation avoidance and scalable concurrency support. jemalloc first came

jemalloc memory allocator 7.7k Jan 7, 2023
The Hoard Memory Allocator: A Fast, Scalable, and Memory-efficient Malloc for Linux, Windows, and Mac.

The Hoard Memory Allocator Copyright (C) 1998-2020 by Emery Berger The Hoard memory allocator is a fast, scalable, and memory-efficient memory allocat

Emery Berger 927 Jan 2, 2023
Public domain cross platform lock free thread caching 16-byte aligned memory allocator implemented in C

rpmalloc - General Purpose Memory Allocator This library provides a public domain cross platform lock free thread caching 16-byte aligned memory alloc

Mattias Jansson 1.7k Dec 28, 2022
A tiny portable C89 memory allocator

mem A tiny portable C89 memory allocator. Usage This is a single-header library. You must include this file alongside #define MEM_IMPLEMENTATION in on

null 11 Nov 20, 2022
Malloc Lab: simple memory allocator using sorted segregated free list

LAB 6: Malloc Lab Main Files mm.{c,h} - Your solution malloc package. mdriver.c - The malloc driver that tests your mm.c file short{1,2}-bal.rep - T

null 1 Feb 28, 2022
Mesh - A memory allocator that automatically reduces the memory footprint of C/C++ applications.

Mesh: Compacting Memory Management for C/C++ Mesh is a drop in replacement for malloc(3) that can transparently recover from memory fragmentation with

PLASMA @ UMass 1.5k Dec 30, 2022
Hardened malloc - Hardened allocator designed for modern systems

Hardened malloc - Hardened allocator designed for modern systems. It has integration into Android's Bionic libc and can be used externally with musl and glibc as a dynamic library for use on other Linux-based platforms. It will gain more portability / integration over time.

GrapheneOS 893 Jan 3, 2023
Snmalloc - Message passing based allocator

snmalloc snmalloc is a high-performance allocator. snmalloc can be used directly in a project as a header-only C++ library, it can be LD_PRELOADed on

Microsoft 1.1k Jan 9, 2023
Allocator bench - bench of various memory allocators

To run benchmarks Install lockless from https://locklessinc.com/downloads/ in lockless_allocator path make Install Hoard from https://github.com/emery

Sam 47 Dec 4, 2022
Custom memory allocators in C++ to improve the performance of dynamic memory allocation

Table of Contents Introduction Build instructions What's wrong with Malloc? Custom allocators Linear Allocator Stack Allocator Pool Allocator Free lis

Mariano Trebino 1.4k Jan 2, 2023
A memory allocation program, it is used for doing an experiment to find out the detail of Microsoft Windows taskmgr performance information

memory-allocation-test A memory allocation program, it is used for doing an experiment to find out the detail of Microsoft Windows taskmgr performance

Chang Wei 4 Dec 22, 2022
A C++ Class and Template Library for Performance Critical Applications

Spirick Tuning A C++ Class and Template Library for Performance Critical Applications Optimized for Performance The Spirick Tuning library provides a

Dietmar Deimling 3 Dec 6, 2021
STL compatible C++ memory allocator library using a new RawAllocator concept that is similar to an Allocator but easier to use and write.

memory The C++ STL allocator model has various flaws. For example, they are fixed to a certain type, because they are almost necessarily required to b

Jonathan Müller 1.2k Dec 26, 2022
STL compatible C++ memory allocator library using a new RawAllocator concept that is similar to an Allocator but easier to use and write.

STL compatible C++ memory allocator library using a new RawAllocator concept that is similar to an Allocator but easier to use and write.

Jonathan Müller 1k Dec 2, 2021
A list of excellent resources for anyone to deepen their understanding with regards to Windows Kernel Exploitation and general low level security.

WinKernel-Resources A list of excellent resources for anyone trying to deepen their understanding with regards to Windows Kernel Exploitation and gene

Vector Security 55 Nov 12, 2022
Simple conservative GC using mimalloc

migc Small and simple library that implements conservative GC using mimalloc API. Features Small and tiny. libmigc.so is just 20KB when linked with mi

playX 34 Jan 1, 2023
The Best and Highest-Leveled and Newest bingding for MiMalloc Ever Existed in Rust

The Best and Highest-Leveled and Newest bingding for MiMalloc Ever Existed in Rust mimalloc 1.7.2 stable Why create this in repo https://github.com/pu

LemonHX 31 Dec 17, 2022