mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-06 23:39:31 +03:00
commit
e9eb1c8cfe
11 changed files with 49 additions and 51 deletions
|
@ -883,7 +883,7 @@ typedef bool (mi_block_visit_fun)(const mi_heap_t* heap, const mi_heap_area_t* a
|
|||
bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_all_blocks, mi_block_visit_fun* visitor, void* arg);
|
||||
|
||||
/// @brief Visit all areas and blocks in abandoned heaps.
|
||||
/// @param subproc_id The sub-process id associated with the abandonded heaps.
|
||||
/// @param subproc_id The sub-process id associated with the abandoned heaps.
|
||||
/// @param heap_tag Visit only abandoned memory with the specified heap tag, use -1 to visit all abandoned memory.
|
||||
/// @param visit_blocks If \a true visits all allocated blocks, otherwise
|
||||
/// \a visitor is only called for every heap area.
|
||||
|
@ -1139,7 +1139,7 @@ to link with the static library. See `test\CMakeLists.txt` for an example.
|
|||
|
||||
### C++
|
||||
For best performance in C++ programs, it is also recommended to override the
|
||||
global `new` and `delete` operators. For convience, mimalloc provides
|
||||
global `new` and `delete` operators. For convenience, mimalloc provides
|
||||
[`mimalloc-new-delete.h`](https://github.com/microsoft/mimalloc/blob/master/include/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`
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# install from an image
|
||||
# download first an appropiate tar.gz image into the current directory
|
||||
# download first an appropriate tar.gz image into the current directory
|
||||
# from: <https://github.com/alpinelinux/docker-alpine/tree/edge/armv7>
|
||||
FROM scratch
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ terms of the MIT license. A copy of the license can be found in the file
|
|||
// --------------------------------------------------------------------------------------------
|
||||
// Atomics
|
||||
// We need to be portable between C, C++, and MSVC.
|
||||
// We base the primitives on the C/C++ atomics and create a mimimal wrapper for MSVC in C compilation mode.
|
||||
// We base the primitives on the C/C++ atomics and create a minimal wrapper for MSVC in C compilation mode.
|
||||
// This is why we try to use only `uintptr_t` and `<type>*` as atomic types.
|
||||
// To gain better insight in the range of used atomics, we use explicitly named memory order operations
|
||||
// instead of passing the memory order as a parameter.
|
||||
|
|
|
@ -10,7 +10,7 @@ terms of the MIT license. A copy of the license can be found in the file
|
|||
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// This file contains the interal API's of mimalloc and various utility
|
||||
// This file contains the internal API's of mimalloc and various utility
|
||||
// functions and macros.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -245,7 +245,7 @@ typedef enum mi_delayed_e {
|
|||
MI_USE_DELAYED_FREE = 0, // push on the owning heap thread delayed list
|
||||
MI_DELAYED_FREEING = 1, // temporary: another thread is accessing the owning heap
|
||||
MI_NO_DELAYED_FREE = 2, // optimize: push on page local thread free queue if another block is already in the heap thread delayed free list
|
||||
MI_NEVER_DELAYED_FREE = 3 // sticky: used for abondoned pages without a owning heap; this only resets on page reclaim
|
||||
MI_NEVER_DELAYED_FREE = 3 // sticky: used for abandoned pages without a owning heap; this only resets on page reclaim
|
||||
} mi_delayed_t;
|
||||
|
||||
|
||||
|
@ -352,7 +352,7 @@ typedef enum mi_page_kind_e {
|
|||
MI_PAGE_MEDIUM, // medium blocks go into 512KiB pages inside a segment
|
||||
MI_PAGE_LARGE, // larger blocks go into a single page spanning a whole segment
|
||||
MI_PAGE_HUGE // a huge page is a single page in a segment of variable size (but still 2MiB aligned)
|
||||
// used for blocks `> MI_LARGE_OBJ_SIZE_MAX` or an aligment `> MI_BLOCK_ALIGNMENT_MAX`.
|
||||
// used for blocks `> MI_LARGE_OBJ_SIZE_MAX` or an alignment `> MI_BLOCK_ALIGNMENT_MAX`.
|
||||
} mi_page_kind_t;
|
||||
|
||||
|
||||
|
|
|
@ -286,7 +286,7 @@ static mi_decl_noinline void* mi_arena_try_alloc_at(mi_arena_t* arena, size_t ar
|
|||
return p;
|
||||
}
|
||||
|
||||
// allocate in a speficic arena
|
||||
// allocate in a specific arena
|
||||
static void* mi_arena_try_alloc_at_id(mi_arena_id_t arena_id, bool match_numa_node, int numa_node, size_t size, size_t alignment,
|
||||
bool commit, bool allow_large, mi_arena_id_t req_arena_id, mi_memid_t* memid )
|
||||
{
|
||||
|
@ -1005,5 +1005,3 @@ int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserv
|
|||
if (err==0 && pages_reserved!=NULL) *pages_reserved = pages;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ static mi_option_desc_t options[_mi_option_last] =
|
|||
{ MI_DEFAULT_DISALLOW_ARENA_ALLOC, UNINIT, MI_OPTION(disallow_arena_alloc) }, // 1 = do not use arena's for allocation (except if using specific arena id's)
|
||||
{ 400, UNINIT, MI_OPTION(retry_on_oom) }, // windows only: retry on out-of-memory for N milli seconds (=400), set to 0 to disable retries.
|
||||
#if defined(MI_VISIT_ABANDONED)
|
||||
{ 1, INITIALIZED, MI_OPTION(visit_abandoned) }, // allow visiting heap blocks in abandonded segments; requires taking locks during reclaim.
|
||||
{ 1, INITIALIZED, MI_OPTION(visit_abandoned) }, // allow visiting heap blocks in abandoned segments; requires taking locks during reclaim.
|
||||
#else
|
||||
{ 0, UNINIT, MI_OPTION(visit_abandoned) },
|
||||
#endif
|
||||
|
@ -368,7 +368,7 @@ static _Atomic(size_t) warning_count; // = 0; // when >= max_warning_count stop
|
|||
// (recursively) invoke malloc again to allocate space for the thread local
|
||||
// variables on demand. This is why we use a _mi_preloading test on such
|
||||
// platforms. However, C code generator may move the initial thread local address
|
||||
// load before the `if` and we therefore split it out in a separate funcion.
|
||||
// load before the `if` and we therefore split it out in a separate function.
|
||||
static mi_decl_thread bool recurse = false;
|
||||
|
||||
static mi_decl_noinline bool mi_recurse_enter_prim(void) {
|
||||
|
|
|
@ -771,7 +771,7 @@ bool _mi_prim_getenv(const char* name, char* result, size_t result_size) {
|
|||
#include <CommonCrypto/CommonRandom.h>
|
||||
|
||||
bool _mi_prim_random_buf(void* buf, size_t buf_len) {
|
||||
// We prefere CCRandomGenerateBytes as it returns an error code while arc4random_buf
|
||||
// We prefer CCRandomGenerateBytes as it returns an error code while arc4random_buf
|
||||
// may fail silently on macOS. See PR #390, and <https://opensource.apple.com/source/Libc/Libc-1439.40.11/gen/FreeBSD/arc4random.c.auto.html>
|
||||
return (CCRandomGenerateBytes(buf, buf_len) == kCCSuccess);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ typedef NTSTATUS (__stdcall *PNtAllocateVirtualMemoryEx)(HANDLE, PVOID*, SIZE_T*
|
|||
static PVirtualAlloc2 pVirtualAlloc2 = NULL;
|
||||
static PNtAllocateVirtualMemoryEx pNtAllocateVirtualMemoryEx = NULL;
|
||||
|
||||
// Similarly, GetNumaProcesorNodeEx is only supported since Windows 7
|
||||
// Similarly, GetNumaProcessorNodeEx is only supported since Windows 7
|
||||
typedef struct MI_PROCESSOR_NUMBER_S { WORD Group; BYTE Number; BYTE Reserved; } MI_PROCESSOR_NUMBER;
|
||||
|
||||
typedef VOID (__stdcall *PGetCurrentProcessorNumberEx)(MI_PROCESSOR_NUMBER* ProcNumber);
|
||||
|
|
|
@ -32,7 +32,7 @@ static uint8_t* mi_segment_raw_page_start(const mi_segment_t* segment, const mi_
|
|||
(i.e. we are careful to not touch the memory until we actually allocate a block there)
|
||||
|
||||
If a thread ends, it "abandons" pages that still contain live blocks.
|
||||
Such segments are abondoned and these can be reclaimed by still running threads,
|
||||
Such segments are abandoned and these can be reclaimed by still running threads,
|
||||
(much like work-stealing).
|
||||
-------------------------------------------------------------------------------- */
|
||||
|
||||
|
@ -276,7 +276,7 @@ static bool mi_page_ensure_committed(mi_segment_t* segment, mi_page_t* page, mi_
|
|||
|
||||
// we re-use the `free` field for the expiration counter. Since this is a
|
||||
// a pointer size field while the clock is always 64-bit we need to guard
|
||||
// against overflow, we use substraction to check for expiry which works
|
||||
// against overflow, we use subtraction to check for expiry which works
|
||||
// as long as the reset delay is under (2^30 - 1) milliseconds (~12 days)
|
||||
static uint32_t mi_page_get_expire( mi_page_t* page ) {
|
||||
return (uint32_t)((uintptr_t)page->free);
|
||||
|
@ -294,7 +294,7 @@ static void mi_page_purge_set_expire(mi_page_t* page) {
|
|||
|
||||
// we re-use the `free` field for the expiration counter. Since this is a
|
||||
// a pointer size field while the clock is always 64-bit we need to guard
|
||||
// against overflow, we use substraction to check for expiry which work
|
||||
// against overflow, we use subtraction to check for expiry which work
|
||||
// as long as the reset delay is under (2^30 - 1) milliseconds (~12 days)
|
||||
static bool mi_page_purge_is_expired(mi_page_t* page, mi_msecs_t now) {
|
||||
int32_t expire = (int32_t)mi_page_get_expire(page);
|
||||
|
@ -789,7 +789,7 @@ When a block is freed in an abandoned segment, the segment
|
|||
is reclaimed into that thread.
|
||||
|
||||
Moreover, if threads are looking for a fresh segment, they
|
||||
will first consider abondoned segments -- these can be found
|
||||
will first consider abandoned segments -- these can be found
|
||||
by scanning the arena memory
|
||||
(segments outside arena memoryare only reclaimed by a free).
|
||||
----------------------------------------------------------- */
|
||||
|
@ -1016,7 +1016,7 @@ static mi_segment_t* mi_segment_try_reclaim(mi_heap_t* heap, size_t block_size,
|
|||
{
|
||||
mi_assert(segment->subproc == heap->tld->segments.subproc); // cursor only visits segments in our sub-process
|
||||
segment->abandoned_visits++;
|
||||
// todo: should we respect numa affinity for abondoned reclaim? perhaps only for the first visit?
|
||||
// todo: should we respect numa affinity for abandoned reclaim? perhaps only for the first visit?
|
||||
// todo: an arena exclusive heap will potentially visit many abandoned unsuitable segments and use many tries
|
||||
// Perhaps we can skip non-suitable ones in a better way?
|
||||
bool is_suitable = _mi_heap_memid_is_suitable(heap, segment->memid);
|
||||
|
|
Loading…
Add table
Reference in a new issue