diff --git a/ide/vs2017/mimalloc-override.vcxproj b/ide/vs2017/mimalloc-override.vcxproj index 7d452b55..8a7f8463 100644 --- a/ide/vs2017/mimalloc-override.vcxproj +++ b/ide/vs2017/mimalloc-override.vcxproj @@ -146,7 +146,6 @@ MaxSpeed true true - true true ../../include MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);NDEBUG @@ -155,6 +154,7 @@ false MultiThreadedDLL Default + false true @@ -173,7 +173,6 @@ MaxSpeed true true - true true ../../include MI_SHARED_LIB;MI_SHARED_LIB_EXPORT;MI_MALLOC_OVERRIDE;%(PreprocessorDefinitions);NDEBUG @@ -182,6 +181,7 @@ false MultiThreadedDLL Default + false true diff --git a/ide/vs2017/mimalloc.vcxproj b/ide/vs2017/mimalloc.vcxproj index 3e453471..854bf921 100644 --- a/ide/vs2017/mimalloc.vcxproj +++ b/ide/vs2017/mimalloc.vcxproj @@ -141,8 +141,6 @@ Level3 MaxSpeed true - true - true true ../../include %(PreprocessorDefinitions);NDEBUG @@ -150,11 +148,9 @@ $(IntDir) false false - AnySuitable - Neither - false - false + Default CompileAsCpp + true true @@ -172,8 +168,6 @@ Level3 MaxSpeed true - true - true true ../../include %(PreprocessorDefinitions);NDEBUG @@ -181,11 +175,9 @@ $(IntDir) false false - AnySuitable - Neither - false - false + Default CompileAsCpp + true true diff --git a/include/mimalloc.h b/include/mimalloc.h index dea4b808..951b1889 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -220,8 +220,8 @@ mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs) mi_a typedef enum mi_option_e { // stable options - mi_option_show_stats, mi_option_show_errors, + mi_option_show_stats, mi_option_verbose, // the following options are experimental mi_option_secure, @@ -232,7 +232,6 @@ typedef enum mi_option_e { mi_option_page_reset, mi_option_cache_reset, mi_option_reset_decommits, - mi_option_reset_discards, _mi_option_last } mi_option_t; diff --git a/src/alloc-override-win.c b/src/alloc-override-win.c index d1d51b9a..0bd05deb 100644 --- a/src/alloc-override-win.c +++ b/src/alloc-override-win.c @@ -666,7 +666,7 @@ static void mi_patches_at_quick_exit(void) { mi_patches_enable_term(); // enter termination phase and patch realloc/free with a no-op } -__declspec(dllexport) BOOL WINAPI DllEntry(HINSTANCE inst, DWORD reason, LPVOID reserved) { +BOOL WINAPI DllEntry(HINSTANCE inst, DWORD reason, LPVOID reserved) { if (reason == DLL_PROCESS_ATTACH) { __security_init_cookie(); } diff --git a/src/init.c b/src/init.c index 95c0dcb8..b2a1cd30 100644 --- a/src/init.c +++ b/src/init.c @@ -425,7 +425,7 @@ static void mi_process_load(void) { if (mi_option_is_enabled(mi_option_reserve_huge_os_pages)) { size_t pages = mi_option_get(mi_option_reserve_huge_os_pages); - double max_secs = (double)pages / 10.0; // 0.1s per page + double max_secs = (double)pages / 5.0; // 0.2s per page mi_reserve_huge_os_pages(pages, max_secs); } } diff --git a/src/options.c b/src/options.c index 1890c865..e9c4a78c 100644 --- a/src/options.c +++ b/src/options.c @@ -34,35 +34,38 @@ typedef enum mi_init_e { typedef struct mi_option_desc_s { long value; // the value mi_init_t init; // is it initialized yet? (from the environment) + mi_option_t option; // for debugging: the option index should match the option const char* name; // option name without `mimalloc_` prefix } mi_option_desc_t; +#define MI_OPTION(opt) mi_option_##opt, #opt +#define MI_OPTION_DESC(opt) {0, UNINIT, MI_OPTION(opt) } + static mi_option_desc_t options[_mi_option_last] = { // stable options - { 0, UNINIT, "show_stats" }, - { MI_DEBUG, UNINIT, "show_errors" }, - { 0, UNINIT, "verbose" }, + { MI_DEBUG, UNINIT, MI_OPTION(show_errors) }, + { 0, UNINIT, MI_OPTION(show_stats) }, + { 0, UNINIT, MI_OPTION(verbose) }, #if MI_SECURE - { MI_SECURE, INITIALIZED, "secure" }, // in a secure build the environment setting is ignored + { MI_SECURE, INITIALIZED, MI_OPTION(secure) }, // in a secure build the environment setting is ignored #else - { 0, UNINIT, "secure" }, + { 0, UNINIT, MI_OPTION(secure) }, #endif // the following options are experimental and not all combinations make sense. - { 1, UNINIT, "eager_commit" }, // note: if eager_region_commit is on, this should be on too. + { 1, UNINIT, MI_OPTION(eager_commit) }, // note: if eager_region_commit is on, this should be on too. #ifdef _WIN32 // and BSD? - { 1, UNINIT, "eager_region_commit" }, + { 1, UNINIT, MI_OPTION(eager_region_commit) }, // don't commit too eagerly on windows (just for looks...) #else - { 1, UNINIT, "eager_region_commit" }, + { 1, UNINIT, MI_OPTION(eager_region_commit) }, #endif - { 0, UNINIT, "large_os_pages" }, // use large OS pages, use only with eager commit to prevent fragmentation of VMA's - { 0, UNINIT, "reserve_huge_os_pages" }, - { 0, UNINIT, "page_reset" }, - { 0, UNINIT, "cache_reset" }, - { 0, UNINIT, "reset_decommits" }, // note: cannot enable this if secure is on - { 0, UNINIT, "reset_discards" } // note: cannot enable this if secure is on + { 0, UNINIT, MI_OPTION(large_os_pages) }, // use large OS pages, use only with eager commit to prevent fragmentation of VMA's + { 0, UNINIT, MI_OPTION(reserve_huge_os_pages) }, + { 0, UNINIT, MI_OPTION(page_reset) }, + { 0, UNINIT, MI_OPTION(cache_reset) }, + { 0, UNINIT, MI_OPTION(reset_decommits) } // note: cannot enable this if secure is on }; static void mi_option_init(mi_option_desc_t* desc); @@ -70,6 +73,7 @@ static void mi_option_init(mi_option_desc_t* desc); long mi_option_get(mi_option_t option) { mi_assert(option >= 0 && option < _mi_option_last); mi_option_desc_t* desc = &options[option]; + mi_assert(desc->option == option); // index should match the option if (mi_unlikely(desc->init == UNINIT)) { mi_option_init(desc); if (option != mi_option_verbose) { @@ -82,6 +86,7 @@ long mi_option_get(mi_option_t option) { void mi_option_set(mi_option_t option, long value) { mi_assert(option >= 0 && option < _mi_option_last); mi_option_desc_t* desc = &options[option]; + mi_assert(desc->option == option); // index should match the option desc->value = value; desc->init = INITIALIZED; } diff --git a/src/os.c b/src/os.c index 525c77a9..b15d58d0 100644 --- a/src/os.c +++ b/src/os.c @@ -198,7 +198,7 @@ static bool mi_os_mem_free(void* addr, size_t size, mi_stats_t* stats) static void* mi_win_virtual_allocx(void* addr, size_t size, size_t try_alignment, DWORD flags) { #if defined(MEM_EXTENDED_PARAMETER_TYPE_BITS) // on modern Windows try use NtAllocateVirtualMemoryEx for 1GiB huge pages - if ((size % (uintptr_t)1 << 20) == 0 /* 1GiB multiple */ + if ((size % (uintptr_t)1 << 30) == 0 /* 1GiB multiple */ && (flags & MEM_LARGE_PAGES) != 0 && (flags & MEM_COMMIT) != 0 && (addr != NULL || try_alignment == 0 || try_alignment % _mi_os_page_size() == 0) && pNtAllocateVirtualMemoryEx != NULL) @@ -215,7 +215,10 @@ static void* mi_win_virtual_allocx(void* addr, size_t size, size_t try_alignment if (err == 0) { return base; } - // else fall back to regular large OS pages + else { + // else fall back to regular large OS pages + _mi_warning_message("unable to allocate huge (1GiB) page, trying large (2MiB) page instead (error %lx)\n", err); + } } // on modern Windows try use VirtualAlloc2 for aligned allocation @@ -276,7 +279,7 @@ static void* mi_unix_mmapx(void* addr, size_t size, size_t try_alignment, int pr void* p = NULL; #if (MI_INTPTR_SIZE >= 8) && !defined(MAP_ALIGNED) // on 64-bit systems, use the virtual address area after 4TiB for 4MiB aligned allocations - static volatile intptr_t aligned_base = ((intptr_t)1 << 42); // starting at 4TiB + static volatile intptr_t aligned_base = ((intptr_t)4 << 40); // starting at 4TiB if (addr==NULL && try_alignment <= MI_SEGMENT_SIZE && (size%MI_SEGMENT_SIZE)==0) { intptr_t hint = mi_atomic_add(&aligned_base,size) - size; if (hint%try_alignment == 0) { @@ -597,9 +600,10 @@ static bool mi_os_resetx(void* addr, size_t size, bool reset, mi_stats_t* stats) #endif #if defined(_WIN32) + // Testing shows that for us (on `malloc-large`) MEM_RESET is 2x faster than DiscardVirtualMemory void* p = VirtualAlloc(start, csize, MEM_RESET, PAGE_READWRITE); mi_assert_internal(p == start); - if (p != start) return false; + if (p != start) return false; #else #if defined(MADV_FREE) static int advice = MADV_FREE; @@ -772,7 +776,7 @@ int mi_reserve_huge_os_pages( size_t pages, double max_secs ) mi_attr_noexcept // Allocate one page at the time but try to place them contiguously // We allocate one page at the time to be able to abort if it takes too long double start_t = _mi_clock_start(); - uint8_t* start = (uint8_t*)((uintptr_t)1 << 43); // 8TiB virtual start address + uint8_t* start = (uint8_t*)((uintptr_t)8 << 40); // 8TiB virtual start address uint8_t* addr = start; // current top of the allocations for (size_t page = 0; page < pages; page++, addr += MI_HUGE_OS_PAGE_SIZE ) { // allocate lorgu pages