-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Add a port of mimalloc, a fast and scalable multithreaded allocator #20651
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3c0ae3a
cc53529
fcef3bc
910e0fa
4b41147
dfb96d1
9c451f3
4715e80
ff348f9
415fa21
072bd56
28afc20
c55872c
862e74d
f717f84
373c343
2dcc313
6d29f45
46d50fd
9139636
fdb22cf
e0a1512
59f363c
795ed0f
fffa2f5
8cfbaad
6ce7901
5df421f
c9e44d6
1dd9d37
aedf114
e55e172
45aacd7
b3e580d
13e1b4c
90b1570
9e1210f
923bb8a
9f252d1
f96a478
c73b406
fe4090d
fbca4bc
bebd586
e520fcd
f40dd26
3ae0e2a
22ac2b0
193311f
6cb2248
879d9b9
bdddfce
4d2393d
3ffdce8
512dccf
9b9232c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -221,6 +221,15 @@ Enable :ref:`debugging-EMCC_DEBUG` to output files for each compilation phase, i | |
|
||
.. _optimizing-code-unsafe-optimisations: | ||
|
||
Allocation | ||
---------- | ||
|
||
The default ``malloc/free`` implementation used is ``dlmalloc``. You can also | ||
pick ``emmalloc`` (``-sMALLOC=emmalloc``) which is smaller but less fast, or | ||
``mimalloc`` (``-sMALLOC=mimalloc``) which is larger but scales better in a | ||
multithreaded application with contention on ``malloc/free`` (see | ||
:ref:`Allocator_performance`). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess we should consider making it the default for threaded builds onces we have enough trust in it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given the code size and memory overhead, I'm not sure. Maybe. Perhaps if we can make it smaller and leaner (like fixing that emmalloc alignment issue #20645). |
||
|
||
Unsafe optimizations | ||
==================== | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2018-2021 Microsoft Corporation, Daan Leijen | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
|
||
This contains mimalloc 4e50d6714d471b72b2285e25a3df6c92db944593 with | ||
Emscripten backend additions. | ||
|
||
Origin: https://github.com/microsoft/mimalloc | ||
|
||
For the Emscripten port design see src/prim/emscripten/prim.c |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* ---------------------------------------------------------------------------- | ||
Copyright (c) 2018-2020 Microsoft Research, Daan Leijen | ||
This is free software; you can redistribute it and/or modify it under the | ||
terms of the MIT license. A copy of the license can be found in the file | ||
"LICENSE" at the root of this distribution. | ||
-----------------------------------------------------------------------------*/ | ||
#pragma once | ||
#ifndef MIMALLOC_NEW_DELETE_H | ||
#define MIMALLOC_NEW_DELETE_H | ||
|
||
// ---------------------------------------------------------------------------- | ||
// This header provides convenient overrides for the new and | ||
// delete operations in C++. | ||
// | ||
// This header should be included in only one source file! | ||
// | ||
// On Windows, or when linking dynamically with mimalloc, these | ||
// can be more performant than the standard new-delete operations. | ||
// See <https://en.cppreference.com/w/cpp/memory/new/operator_new> | ||
// --------------------------------------------------------------------------- | ||
#if defined(__cplusplus) | ||
#include <new> | ||
#include <mimalloc.h> | ||
|
||
#if defined(_MSC_VER) && defined(_Ret_notnull_) && defined(_Post_writable_byte_size_) | ||
// stay consistent with VCRT definitions | ||
#define mi_decl_new(n) mi_decl_nodiscard mi_decl_restrict _Ret_notnull_ _Post_writable_byte_size_(n) | ||
#define mi_decl_new_nothrow(n) mi_decl_nodiscard mi_decl_restrict _Ret_maybenull_ _Success_(return != NULL) _Post_writable_byte_size_(n) | ||
#else | ||
#define mi_decl_new(n) mi_decl_nodiscard mi_decl_restrict | ||
#define mi_decl_new_nothrow(n) mi_decl_nodiscard mi_decl_restrict | ||
#endif | ||
|
||
void operator delete(void* p) noexcept { mi_free(p); }; | ||
void operator delete[](void* p) noexcept { mi_free(p); }; | ||
|
||
void operator delete (void* p, const std::nothrow_t&) noexcept { mi_free(p); } | ||
void operator delete[](void* p, const std::nothrow_t&) noexcept { mi_free(p); } | ||
|
||
mi_decl_new(n) void* operator new(std::size_t n) noexcept(false) { return mi_new(n); } | ||
mi_decl_new(n) void* operator new[](std::size_t n) noexcept(false) { return mi_new(n); } | ||
|
||
mi_decl_new_nothrow(n) void* operator new (std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); return mi_new_nothrow(n); } | ||
mi_decl_new_nothrow(n) void* operator new[](std::size_t n, const std::nothrow_t& tag) noexcept { (void)(tag); return mi_new_nothrow(n); } | ||
|
||
#if (__cplusplus >= 201402L || _MSC_VER >= 1916) | ||
void operator delete (void* p, std::size_t n) noexcept { mi_free_size(p,n); }; | ||
void operator delete[](void* p, std::size_t n) noexcept { mi_free_size(p,n); }; | ||
#endif | ||
|
||
#if (__cplusplus > 201402L || defined(__cpp_aligned_new)) | ||
void operator delete (void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); } | ||
void operator delete[](void* p, std::align_val_t al) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); } | ||
void operator delete (void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast<size_t>(al)); }; | ||
void operator delete[](void* p, std::size_t n, std::align_val_t al) noexcept { mi_free_size_aligned(p, n, static_cast<size_t>(al)); }; | ||
void operator delete (void* p, std::align_val_t al, const std::nothrow_t&) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); } | ||
void operator delete[](void* p, std::align_val_t al, const std::nothrow_t&) noexcept { mi_free_aligned(p, static_cast<size_t>(al)); } | ||
|
||
void* operator new (std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast<size_t>(al)); } | ||
void* operator new[](std::size_t n, std::align_val_t al) noexcept(false) { return mi_new_aligned(n, static_cast<size_t>(al)); } | ||
void* operator new (std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast<size_t>(al)); } | ||
void* operator new[](std::size_t n, std::align_val_t al, const std::nothrow_t&) noexcept { return mi_new_aligned_nothrow(n, static_cast<size_t>(al)); } | ||
#endif | ||
#endif | ||
|
||
#endif // MIMALLOC_NEW_DELETE_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/* ---------------------------------------------------------------------------- | ||
Copyright (c) 2018-2020 Microsoft Research, Daan Leijen | ||
This is free software; you can redistribute it and/or modify it under the | ||
terms of the MIT license. A copy of the license can be found in the file | ||
"LICENSE" at the root of this distribution. | ||
-----------------------------------------------------------------------------*/ | ||
#pragma once | ||
#ifndef MIMALLOC_OVERRIDE_H | ||
#define MIMALLOC_OVERRIDE_H | ||
|
||
/* ---------------------------------------------------------------------------- | ||
This header can be used to statically redirect malloc/free and new/delete | ||
to the mimalloc variants. This can be useful if one can include this file on | ||
each source file in a project (but be careful when using external code to | ||
not accidentally mix pointers from different allocators). | ||
-----------------------------------------------------------------------------*/ | ||
|
||
#include <mimalloc.h> | ||
|
||
// Standard C allocation | ||
#define malloc(n) mi_malloc(n) | ||
#define calloc(n,c) mi_calloc(n,c) | ||
#define realloc(p,n) mi_realloc(p,n) | ||
#define free(p) mi_free(p) | ||
|
||
#define strdup(s) mi_strdup(s) | ||
#define strndup(s,n) mi_strndup(s,n) | ||
#define realpath(f,n) mi_realpath(f,n) | ||
|
||
// Microsoft extensions | ||
#define _expand(p,n) mi_expand(p,n) | ||
#define _msize(p) mi_usable_size(p) | ||
#define _recalloc(p,n,c) mi_recalloc(p,n,c) | ||
|
||
#define _strdup(s) mi_strdup(s) | ||
#define _strndup(s,n) mi_strndup(s,n) | ||
#define _wcsdup(s) (wchar_t*)mi_wcsdup((const unsigned short*)(s)) | ||
#define _mbsdup(s) mi_mbsdup(s) | ||
#define _dupenv_s(b,n,v) mi_dupenv_s(b,n,v) | ||
#define _wdupenv_s(b,n,v) mi_wdupenv_s((unsigned short*)(b),n,(const unsigned short*)(v)) | ||
|
||
// Various Posix and Unix variants | ||
#define reallocf(p,n) mi_reallocf(p,n) | ||
#define malloc_size(p) mi_usable_size(p) | ||
#define malloc_usable_size(p) mi_usable_size(p) | ||
#define cfree(p) mi_free(p) | ||
|
||
#define valloc(n) mi_valloc(n) | ||
#define pvalloc(n) mi_pvalloc(n) | ||
#define reallocarray(p,s,n) mi_reallocarray(p,s,n) | ||
#define reallocarr(p,s,n) mi_reallocarr(p,s,n) | ||
#define memalign(a,n) mi_memalign(a,n) | ||
#define aligned_alloc(a,n) mi_aligned_alloc(a,n) | ||
#define posix_memalign(p,a,n) mi_posix_memalign(p,a,n) | ||
#define _posix_memalign(p,a,n) mi_posix_memalign(p,a,n) | ||
|
||
// Microsoft aligned variants | ||
#define _aligned_malloc(n,a) mi_malloc_aligned(n,a) | ||
#define _aligned_realloc(p,n,a) mi_realloc_aligned(p,n,a) | ||
#define _aligned_recalloc(p,s,n,a) mi_aligned_recalloc(p,s,n,a) | ||
#define _aligned_msize(p,a,o) mi_usable_size(p) | ||
#define _aligned_free(p) mi_free(p) | ||
#define _aligned_offset_malloc(n,a,o) mi_malloc_aligned_at(n,a,o) | ||
#define _aligned_offset_realloc(p,n,a,o) mi_realloc_aligned_at(p,n,a,o) | ||
#define _aligned_offset_recalloc(p,s,n,a,o) mi_recalloc_aligned_at(p,s,n,a,o) | ||
|
||
#endif // MIMALLOC_OVERRIDE_H |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any reason someone would want to use mimalloc instead of dlmalloc when not building with threads?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mimalloc is actually faster even with a single core, see the first chart. (But it is substantially larger so I doubt it would be a common thing.)