diff --git a/CMakeLists.txt b/CMakeLists.txt index deb5131b..e18e0ea3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,6 +83,19 @@ else() set(mi_defines "") endif() +# pass git revision as a define +if(EXISTS "${CMAKE_SOURCE_DIR}/.git/index") + find_package(Git) + if(GIT_FOUND) + execute_process(COMMAND ${GIT_EXECUTABLE} "describe" OUTPUT_VARIABLE mi_git_describe RESULT_VARIABLE mi_git_res ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + if(mi_git_res EQUAL "0") + list(APPEND mi_defines "MI_GIT_DESCRIBE=${mi_git_describe}") + # add to dependencies so we rebuild if the git head commit changes + set_property(GLOBAL APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/.git/index") + endif() + endif() +endif() + # ----------------------------------------------------------------------------- # Convenience: set default build type and compiler depending on the build directory # ----------------------------------------------------------------------------- @@ -514,6 +527,7 @@ else() endif() endif() + # ----------------------------------------------------------------------------- # Install and output names # ----------------------------------------------------------------------------- @@ -544,6 +558,7 @@ if(MI_TRACK_ASAN) set(mi_libname "${mi_libname}-asan") endif() string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LC) +list(APPEND mi_defines "MI_CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE_LC}") #todo: multi-config project needs $ ? if(NOT(CMAKE_BUILD_TYPE_LC MATCHES "^(release|relwithdebinfo|minsizerel|none)$")) set(mi_libname "${mi_libname}-${CMAKE_BUILD_TYPE_LC}") #append build type (e.g. -debug) if not a release version endif() diff --git a/include/mimalloc/types.h b/include/mimalloc/types.h index ba3c43fa..cb846fb7 100644 --- a/include/mimalloc/types.h +++ b/include/mimalloc/types.h @@ -250,7 +250,7 @@ typedef struct mi_block_s { #define MI_PAGE_FLAG_MASK MI_ZU(0x03) typedef size_t mi_page_flags_t; -// There are two special threadid's: 0 for abandoned threads, and 4 for abandoned & mapped threads -- +// There are two special threadid's: 0 for abandoned threads, and 4 for abandoned & mapped threads -- // abandoned-mapped pages are abandoned but also mapped in an arena so can be quickly found for reuse. #define MI_THREADID_ABANDONED MI_ZU(0) #define MI_THREADID_ABANDONED_MAPPED (MI_PAGE_FLAG_MASK + 1) @@ -459,15 +459,13 @@ struct mi_heap_s { #endif typedef struct mi_stat_count_s { - int64_t allocated; - int64_t freed; + int64_t total; int64_t peak; int64_t current; } mi_stat_count_t; typedef struct mi_stat_counter_s { int64_t total; - int64_t count; } mi_stat_counter_t; typedef struct mi_stats_s { @@ -510,11 +508,13 @@ void __mi_stat_increase(mi_stat_count_t* stat, size_t amount); void __mi_stat_decrease(mi_stat_count_t* stat, size_t amount); void __mi_stat_increase_mt(mi_stat_count_t* stat, size_t amount); void __mi_stat_decrease_mt(mi_stat_count_t* stat, size_t amount); -// adjust stat in special cases to compensate for double counting -void __mi_stat_adjust_increase(mi_stat_count_t* stat, size_t amount, bool on_alloc); -void __mi_stat_adjust_decrease(mi_stat_count_t* stat, size_t amount, bool on_free); -void __mi_stat_adjust_increase_mt(mi_stat_count_t* stat, size_t amount, bool on_alloc); -void __mi_stat_adjust_decrease_mt(mi_stat_count_t* stat, size_t amount, bool on_free); + +// adjust stat in special cases to compensate for double counting (and does not adjust peak values and can decrease the total) +void __mi_stat_adjust_increase(mi_stat_count_t* stat, size_t amount); +void __mi_stat_adjust_decrease(mi_stat_count_t* stat, size_t amount); +void __mi_stat_adjust_increase_mt(mi_stat_count_t* stat, size_t amount); +void __mi_stat_adjust_decrease_mt(mi_stat_count_t* stat, size_t amount); + // counters can just be increased void __mi_stat_counter_increase(mi_stat_counter_t* stat, size_t amount); void __mi_stat_counter_increase_mt(mi_stat_counter_t* stat, size_t amount); @@ -526,8 +526,6 @@ void __mi_stat_counter_increase_mt(mi_stat_counter_t* stat, size_t amount); #define mi_debug_stat_increase_mt(stat,amount) __mi_stat_increase_mt( &(stat), amount) #define mi_debug_stat_decrease_mt(stat,amount) __mi_stat_decrease_mt( &(stat), amount) #define mi_debug_stat_counter_increase_mt(stat,amount) __mi_stat_counter_increase_mt( &(stat), amount) -#define mi_debug_stat_adjust_increase_mt(stat,amnt,b) __mi_stat_adjust_increase_mt( &(stat), amnt, b) -#define mi_debug_stat_adjust_decrease_mt(stat,amnt,b) __mi_stat_adjust_decrease_mt( &(stat), amnt, b) #else #define mi_debug_stat_increase(stat,amount) ((void)0) #define mi_debug_stat_decrease(stat,amount) ((void)0) @@ -535,22 +533,19 @@ void __mi_stat_counter_increase_mt(mi_stat_counter_t* stat, size_t amount); #define mi_debug_stat_increase_mt(stat,amount) ((void)0) #define mi_debug_stat_decrease_mt(stat,amount) ((void)0) #define mi_debug_stat_counter_increase_mt(stat,amount) ((void)0) -#define mi_debug_stat_adjust_increase(stat,amnt,b) ((void)0) -#define mi_debug_stat_adjust_decrease(stat,amnt,b) ((void)0) #endif #define mi_subproc_stat_counter_increase(subproc,stat,amount) __mi_stat_counter_increase_mt( &(subproc)->stats.stat, amount) #define mi_subproc_stat_increase(subproc,stat,amount) __mi_stat_increase_mt( &(subproc)->stats.stat, amount) #define mi_subproc_stat_decrease(subproc,stat,amount) __mi_stat_decrease_mt( &(subproc)->stats.stat, amount) -#define mi_subproc_stat_adjust_increase(subproc,stat,amnt,b) __mi_stat_adjust_increase_mt( &(subproc)->stats.stat, amnt, b) -#define mi_subproc_stat_adjust_decrease(subproc,stat,amnt,b) __mi_stat_adjust_decrease_mt( &(subproc)->stats.stat, amnt, b) +#define mi_subproc_stat_adjust_increase(subproc,stat,amnt) __mi_stat_adjust_increase_mt( &(subproc)->stats.stat, amnt) +#define mi_subproc_stat_adjust_decrease(subproc,stat,amnt) __mi_stat_adjust_decrease_mt( &(subproc)->stats.stat, amnt) #define mi_tld_stat_counter_increase(tld,stat,amount) __mi_stat_counter_increase( &(tld)->stats.stat, amount) #define mi_tld_stat_increase(tld,stat,amount) __mi_stat_increase( &(tld)->stats.stat, amount) #define mi_tld_stat_decrease(tld,stat,amount) __mi_stat_decrease( &(tld)->stats.stat, amount) -#define mi_tld_stat_adjust_increase(tld,stat,amnt,b) __mi_stat_adjust_increase( &(tld)->stats.stat, amnt, b) -#define mi_tld_stat_adjust_decrease(tld,stat,amnt,b) __mi_stat_adjust_decrease( &(tld)->stats.stat, amnt, b) - +#define mi_tld_stat_adjust_increase(tld,stat,amnt) __mi_stat_adjust_increase( &(tld)->stats.stat, amnt) +#define mi_tld_stat_adjust_decrease(tld,stat,amnt) __mi_stat_adjust_decrease( &(tld)->stats.stat, amnt) #define mi_os_stat_counter_increase(stat,amount) mi_subproc_stat_counter_increase(_mi_subproc(),stat,amount) #define mi_os_stat_increase(stat,amount) mi_subproc_stat_increase(_mi_subproc(),stat,amount) diff --git a/src/arena.c b/src/arena.c index 16030951..6abed6bc 100644 --- a/src/arena.c +++ b/src/arena.c @@ -160,7 +160,7 @@ static mi_arena_t* mi_page_arena(mi_page_t* page, size_t* slice_index, size_t* s return mi_arena_from_memid(page->memid, slice_index, slice_count); } -static size_t mi_page_full_size(mi_page_t* page) { +static size_t mi_page_full_size(mi_page_t* page) { if (page->memid.memkind == MI_MEM_ARENA) { return page->memid.mem.arena.slice_count * MI_ARENA_SLICE_SIZE; } @@ -209,10 +209,6 @@ static mi_decl_noinline void* mi_arena_try_alloc_at( // we set the bits first since we own these slices (they are no longer free) size_t already_committed_count = 0; mi_bitmap_setN(arena->slices_committed, slice_index, slice_count, &already_committed_count); - // adjust the stats so we don't double count the commits - //if (already_committed_count > 0) { - // mi_subproc_stat_adjust_decrease(arena->subproc, committed, mi_size_of_slices(already_committed_count), true /* on alloc */); - //} // now actually commit bool commit_zero = false; if (!_mi_os_commit_ex(p, mi_size_of_slices(slice_count), &commit_zero, mi_size_of_slices(slice_count - already_committed_count))) { @@ -315,20 +311,18 @@ static bool mi_arena_reserve(mi_subproc_t* subproc, size_t req_size, bool allow_ // on an OS with overcommit (Linux) we don't count the commit yet as it is on-demand. Once a slice // is actually allocated for the first time it will be counted. const bool adjust = (overcommit && arena_commit); - if (adjust) { - mi_subproc_stat_adjust_decrease( subproc, committed, arena_reserve, true /* on alloc */); - } + if (adjust) { mi_subproc_stat_adjust_decrease( subproc, committed, arena_reserve); } // and try to reserve the arena int err = mi_reserve_os_memory_ex2(subproc, arena_reserve, arena_commit, allow_large, false /* exclusive? */, arena_id); if (err != 0) { - if (adjust) { mi_subproc_stat_adjust_increase( subproc, committed, arena_reserve, true); } // roll back + if (adjust) { mi_subproc_stat_adjust_increase( subproc, committed, arena_reserve); } // roll back // failed, try a smaller size? const size_t small_arena_reserve = (MI_SIZE_BITS == 32 ? 128*MI_MiB : 1*MI_GiB); - if (adjust) { mi_subproc_stat_adjust_decrease( subproc, committed, arena_reserve, true); } + if (adjust) { mi_subproc_stat_adjust_decrease( subproc, committed, arena_reserve); } if (arena_reserve > small_arena_reserve) { // try again err = mi_reserve_os_memory_ex(small_arena_reserve, arena_commit, allow_large, false /* exclusive? */, arena_id); - if (err != 0 && adjust) { mi_subproc_stat_adjust_increase( subproc, committed, arena_reserve, true); } // roll back + if (err != 0 && adjust) { mi_subproc_stat_adjust_increase( subproc, committed, arena_reserve); } // roll back } } return (err==0); @@ -918,7 +912,7 @@ bool _mi_arenas_page_try_reabandon_to_mapped(mi_page_t* page) { else { mi_tld_t* tld = _mi_thread_tld(); mi_tld_stat_counter_increase( tld, pages_reabandon_full, 1); - mi_tld_stat_adjust_decrease( tld, pages_abandoned, 1, true /* on alloc */); // adjust as we are not abandoning fresh + mi_tld_stat_adjust_decrease( tld, pages_abandoned, 1); // adjust as we are not abandoning fresh _mi_arenas_page_abandon(page,tld); return true; } diff --git a/src/init.c b/src/init.c index 4cac1c18..2c7bf109 100644 --- a/src/init.c +++ b/src/init.c @@ -65,11 +65,11 @@ const mi_page_t _mi_page_empty = { QNULL(MI_LARGE_MAX_OBJ_WSIZE + 1 /* 655360, Huge queue */), \ QNULL(MI_LARGE_MAX_OBJ_WSIZE + 2) /* Full queue */ } -#define MI_STAT_COUNT_NULL() {0,0,0,0} +#define MI_STAT_COUNT_NULL() {0,0,0} // Empty statistics #if MI_STAT>1 -#define MI_STAT_COUNT_END_NULL() , { MI_STAT_COUNT_NULL(), MI_INIT32(MI_STAT_COUNT_NULL) } +#define MI_STAT_COUNT_END_NULL() , { MI_INIT64(MI_STAT_COUNT_NULL), MI_INIT8(MI_STAT_COUNT_NULL), MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL() } #else #define MI_STAT_COUNT_END_NULL() #endif @@ -81,10 +81,10 @@ const mi_page_t _mi_page_empty = { MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ MI_STAT_COUNT_NULL(), MI_STAT_COUNT_NULL(), \ - { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ - { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ - { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, \ - { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } \ + { 0 }, { 0 }, { 0 }, { 0 }, \ + { 0 }, { 0 }, { 0 }, { 0 }, \ + { 0 }, { 0 }, { 0 }, { 0 }, \ + { 0 }, { 0 }, { 0 }, { 0 } \ MI_STAT_COUNT_END_NULL() // -------------------------------------------------------- @@ -262,7 +262,7 @@ static void mi_heap_main_init(void) { heap_main.page_full_retain = mi_option_get_clamp(mi_option_page_full_retain, -1, 32); mi_subproc_main_init(); - mi_tld_main_init(); + mi_tld_main_init(); } } @@ -604,7 +604,7 @@ void _mi_heap_set_default_direct(mi_heap_t* heap) { void mi_thread_set_in_threadpool(void) mi_attr_noexcept { mi_tld_t* tld = mi_tld(); - if (tld!=NULL) { + if (tld!=NULL) { tld->is_in_threadpool = true; } } @@ -678,7 +678,7 @@ void mi_process_init(void) mi_attr_noexcept { if (!mi_atomic_once(&process_init)) return; _mi_process_is_initialized = true; _mi_verbose_message("process init: 0x%zx\n", _mi_thread_id()); - + mi_detect_cpu_features(); _mi_os_init(); _mi_page_map_init(); diff --git a/src/options.c b/src/options.c index 91cf0b37..1520350e 100644 --- a/src/options.c +++ b/src/options.c @@ -189,7 +189,7 @@ void _mi_options_init(void) { mi_add_stderr_output(); // now it safe to use stderr for output for(int i = 0; i < _mi_option_last; i++ ) { mi_option_t option = (mi_option_t)i; - mi_option_get(option); // initialize + long l = mi_option_get(option); MI_UNUSED(l); // initialize } mi_max_error_count = mi_option_get(mi_option_max_errors); mi_max_warning_count = mi_option_get(mi_option_max_warnings); @@ -204,24 +204,47 @@ void _mi_options_init(void) { mi_options_print(); } -void mi_options_print(void) mi_attr_noexcept +#define mi_stringifyx(str) #str // and stringify +#define mi_stringify(str) mi_stringifyx(str) // expand + +void mi_options_print(void) mi_attr_noexcept { // show version const int vermajor = MI_MALLOC_VERSION/100; const int verminor = (MI_MALLOC_VERSION%100)/10; const int verpatch = (MI_MALLOC_VERSION%10); - _mi_verbose_message("v%i.%i.%i (built on %s, %s)\n", vermajor, verminor, verpatch, __DATE__, __TIME__); + _mi_verbose_message("v%i.%i.%i%s%s (built on %s, %s)\n", vermajor, verminor, verpatch, + #if defined(MI_CMAKE_BUILD_TYPE) + ", " mi_stringify(MI_CMAKE_BUILD_TYPE) + #else + "" + #endif + , + #if defined(MI_GIT_DESCRIBE) + ", git " mi_stringify(MI_GIT_DESCRIBE) + #else + "" + #endif + , __DATE__, __TIME__); // show options for (int i = 0; i < _mi_option_last; i++) { mi_option_t option = (mi_option_t)i; - mi_option_get(option); + long l = mi_option_get(option); MI_UNUSED(l); // possibly initialize mi_option_desc_t* desc = &options[option]; _mi_verbose_message("option '%s': %ld %s\n", desc->name, desc->value, (mi_option_has_size_in_kib(option) ? "KiB" : "")); - } + } + + // show build configuration + _mi_verbose_message("debug level : %d\n", MI_DEBUG ); + _mi_verbose_message("secure level: %d\n", MI_SECURE ); + _mi_verbose_message("mem tracking: %s\n", MI_TRACK_TOOL); #if MI_GUARDED _mi_verbose_message("guarded build: %s\n", mi_option_get(mi_option_guarded_sample_rate) != 0 ? "enabled" : "disabled"); #endif + #if MI_TSAN + _mi_verbose_message("thread santizer enabled\n"); + #endif } long _mi_option_get_fast(mi_option_t option) { diff --git a/src/stats.c b/src/stats.c index d8450a84..56669629 100644 --- a/src/stats.c +++ b/src/stats.c @@ -25,10 +25,7 @@ static void mi_stat_update_mt(mi_stat_count_t* stat, int64_t amount) { int64_t current = mi_atomic_addi64_relaxed(&stat->current, amount); mi_atomic_maxi64_relaxed(&stat->peak, current + amount); if (amount > 0) { - mi_atomic_addi64_relaxed(&stat->allocated, amount); - } - else { - mi_atomic_addi64_relaxed(&stat->freed, -amount); + mi_atomic_addi64_relaxed(&stat->total, amount); } } @@ -36,44 +33,16 @@ static void mi_stat_update(mi_stat_count_t* stat, int64_t amount) { if (amount == 0) return; // add thread local stat->current += amount; - if (stat->current > stat->peak) stat->peak = stat->current; - if (amount > 0) { - stat->allocated += amount; - } - else { - stat->freed += -amount; - } + if (stat->current > stat->peak) { stat->peak = stat->current; } + if (amount > 0) { stat->total += amount; } } -// Adjust stats to compensate; for example before committing a range, -// first adjust downwards with parts that were already committed so -// we avoid double counting. -static void mi_stat_adjust_mt(mi_stat_count_t* stat, int64_t amount, bool on_alloc) { - if (amount == 0) return; - // adjust atomically - mi_atomic_addi64_relaxed(&stat->current, amount); - mi_atomic_addi64_relaxed((on_alloc ? &stat->allocated : &stat->freed), amount); -} - -static void mi_stat_adjust(mi_stat_count_t* stat, int64_t amount, bool on_alloc) { - if (amount == 0) return; - stat->current += amount; - if (on_alloc) { - stat->allocated += amount; - } - else { - stat->freed += amount; - } -} - void __mi_stat_counter_increase_mt(mi_stat_counter_t* stat, size_t amount) { - mi_atomic_addi64_relaxed(&stat->count, 1); mi_atomic_addi64_relaxed(&stat->total, (int64_t)amount); } void __mi_stat_counter_increase(mi_stat_counter_t* stat, size_t amount) { - stat->count++; stat->total += amount; } @@ -91,77 +60,91 @@ void __mi_stat_decrease(mi_stat_count_t* stat, size_t amount) { mi_stat_update(stat, -((int64_t)amount)); } -void __mi_stat_adjust_increase_mt(mi_stat_count_t* stat, size_t amount, bool on_alloc) { - mi_stat_adjust_mt(stat, (int64_t)amount, on_alloc); -} -void __mi_stat_adjust_increase(mi_stat_count_t* stat, size_t amount, bool on_alloc) { - mi_stat_adjust(stat, (int64_t)amount, on_alloc); + +// Adjust stats to compensate; for example before committing a range, +// first adjust downwards with parts that were already committed so +// we avoid double counting. +static void mi_stat_adjust_mt(mi_stat_count_t* stat, int64_t amount) { + if (amount == 0) return; + // adjust atomically + mi_atomic_addi64_relaxed(&stat->current, amount); + mi_atomic_addi64_relaxed(&stat->total, amount); } -void __mi_stat_adjust_decrease_mt(mi_stat_count_t* stat, size_t amount, bool on_alloc) { - mi_stat_adjust_mt(stat, -((int64_t)amount), on_alloc); +static void mi_stat_adjust(mi_stat_count_t* stat, int64_t amount) { + if (amount == 0) return; + stat->current += amount; + stat->total += amount; } -void __mi_stat_adjust_decrease(mi_stat_count_t* stat, size_t amount, bool on_alloc) { - mi_stat_adjust(stat, -((int64_t)amount), on_alloc); + +void __mi_stat_adjust_increase_mt(mi_stat_count_t* stat, size_t amount) { + mi_stat_adjust_mt(stat, (int64_t)amount); +} +void __mi_stat_adjust_increase(mi_stat_count_t* stat, size_t amount) { + mi_stat_adjust(stat, (int64_t)amount); +} +void __mi_stat_adjust_decrease_mt(mi_stat_count_t* stat, size_t amount) { + mi_stat_adjust_mt(stat, -((int64_t)amount)); +} +void __mi_stat_adjust_decrease(mi_stat_count_t* stat, size_t amount) { + mi_stat_adjust(stat, -((int64_t)amount)); } // must be thread safe as it is called from stats_merge -static void mi_stat_add(mi_stat_count_t* stat, const mi_stat_count_t* src, int64_t unit) { +static void mi_stat_add(mi_stat_count_t* stat, const mi_stat_count_t* src) { if (stat==src) return; - if (src->allocated==0 && src->freed==0) return; - mi_atomic_addi64_relaxed( &stat->allocated, src->allocated * unit); - mi_atomic_addi64_relaxed( &stat->current, src->current * unit); - mi_atomic_addi64_relaxed( &stat->freed, src->freed * unit); - // peak scores do not work across threads.. - mi_atomic_addi64_relaxed( &stat->peak, src->peak * unit); + if (src->total==0) return; + mi_atomic_addi64_relaxed( &stat->total, src->total); + mi_atomic_addi64_relaxed( &stat->current, src->current); + // peak scores do really not work across threads ... we use conservative max + mi_atomic_maxi64_relaxed( &stat->peak, src->peak); // or: mi_atomic_addi64_relaxed( &stat->peak, src->peak); } -static void mi_stat_counter_add(mi_stat_counter_t* stat, const mi_stat_counter_t* src, int64_t unit) { +static void mi_stat_counter_add(mi_stat_counter_t* stat, const mi_stat_counter_t* src) { if (stat==src) return; - mi_atomic_addi64_relaxed( &stat->total, src->total * unit); - mi_atomic_addi64_relaxed( &stat->count, src->count * unit); + mi_atomic_addi64_relaxed( &stat->total, src->total); } // must be thread safe as it is called from stats_merge static void mi_stats_add(mi_stats_t* stats, const mi_stats_t* src) { if (stats==src) return; - mi_stat_add(&stats->pages, &src->pages,1); - mi_stat_add(&stats->reserved, &src->reserved, 1); - mi_stat_add(&stats->committed, &src->committed, 1); - mi_stat_add(&stats->reset, &src->reset, 1); - mi_stat_add(&stats->purged, &src->purged, 1); - mi_stat_add(&stats->page_committed, &src->page_committed, 1); + mi_stat_add(&stats->pages, &src->pages); + mi_stat_add(&stats->reserved, &src->reserved); + mi_stat_add(&stats->committed, &src->committed); + mi_stat_add(&stats->reset, &src->reset); + mi_stat_add(&stats->purged, &src->purged); + mi_stat_add(&stats->page_committed, &src->page_committed); - mi_stat_add(&stats->pages_abandoned, &src->pages_abandoned, 1); - mi_stat_add(&stats->threads, &src->threads, 1); + mi_stat_add(&stats->pages_abandoned, &src->pages_abandoned); + mi_stat_add(&stats->threads, &src->threads); - mi_stat_add(&stats->malloc, &src->malloc, 1); - mi_stat_add(&stats->normal, &src->normal, 1); - mi_stat_add(&stats->huge, &src->huge, 1); - mi_stat_add(&stats->giant, &src->giant, 1); + mi_stat_add(&stats->malloc, &src->malloc); + mi_stat_add(&stats->normal, &src->normal); + mi_stat_add(&stats->huge, &src->huge); + mi_stat_add(&stats->giant, &src->giant); - mi_stat_counter_add(&stats->pages_extended, &src->pages_extended, 1); - mi_stat_counter_add(&stats->mmap_calls, &src->mmap_calls, 1); - mi_stat_counter_add(&stats->commit_calls, &src->commit_calls, 1); - mi_stat_counter_add(&stats->reset_calls, &src->reset_calls, 1); - mi_stat_counter_add(&stats->purge_calls, &src->purge_calls, 1); + mi_stat_counter_add(&stats->pages_extended, &src->pages_extended); + mi_stat_counter_add(&stats->mmap_calls, &src->mmap_calls); + mi_stat_counter_add(&stats->commit_calls, &src->commit_calls); + mi_stat_counter_add(&stats->reset_calls, &src->reset_calls); + mi_stat_counter_add(&stats->purge_calls, &src->purge_calls); - mi_stat_counter_add(&stats->page_no_retire, &src->page_no_retire, 1); - mi_stat_counter_add(&stats->searches, &src->searches, 1); - mi_stat_counter_add(&stats->normal_count, &src->normal_count, 1); - mi_stat_counter_add(&stats->huge_count, &src->huge_count, 1); - mi_stat_counter_add(&stats->guarded_alloc_count, &src->guarded_alloc_count, 1); + mi_stat_counter_add(&stats->page_no_retire, &src->page_no_retire); + mi_stat_counter_add(&stats->searches, &src->searches); + mi_stat_counter_add(&stats->normal_count, &src->normal_count); + mi_stat_counter_add(&stats->huge_count, &src->huge_count); + mi_stat_counter_add(&stats->guarded_alloc_count, &src->guarded_alloc_count); - mi_stat_counter_add(&stats->pages_extended, &src->pages_extended, 1); - mi_stat_counter_add(&stats->pages_reclaim_on_alloc, &src->pages_reclaim_on_alloc, 1); - mi_stat_counter_add(&stats->pages_reclaim_on_free, &src->pages_reclaim_on_free, 1); - mi_stat_counter_add(&stats->pages_reabandon_full, &src->pages_reabandon_full, 1); - mi_stat_counter_add(&stats->pages_unabandon_busy_wait, &src->pages_unabandon_busy_wait, 1); + mi_stat_counter_add(&stats->pages_extended, &src->pages_extended); + mi_stat_counter_add(&stats->pages_reclaim_on_alloc, &src->pages_reclaim_on_alloc); + mi_stat_counter_add(&stats->pages_reclaim_on_free, &src->pages_reclaim_on_free); + mi_stat_counter_add(&stats->pages_reabandon_full, &src->pages_reabandon_full); + mi_stat_counter_add(&stats->pages_unabandon_busy_wait, &src->pages_unabandon_busy_wait); #if MI_STAT>1 for (size_t i = 0; i <= MI_BIN_HUGE; i++) { - if (src->normal_bins[i].allocated > 0 || src->normal_bins[i].freed > 0) { - mi_stat_add(&stats->normal_bins[i], &src->normal_bins[i], 1); + if (src->normal_bins[i].total > 0) { + mi_stat_add(&stats->normal_bins[i], &src->normal_bins[i]); } } #endif @@ -217,26 +200,26 @@ static void mi_stat_print_ex(const mi_stat_count_t* stat, const char* msg, int64 if (unit != 0) { if (unit > 0) { mi_print_amount(stat->peak, unit, out, arg); - mi_print_amount(stat->allocated, unit, out, arg); - mi_print_amount(stat->freed, unit, out, arg); + mi_print_amount(stat->total, unit, out, arg); + // mi_print_amount(stat->freed, unit, out, arg); mi_print_amount(stat->current, unit, out, arg); mi_print_amount(unit, 1, out, arg); - mi_print_count(stat->allocated, unit, out, arg); + mi_print_count(stat->total, unit, out, arg); } else { mi_print_amount(stat->peak, -1, out, arg); - mi_print_amount(stat->allocated, -1, out, arg); - mi_print_amount(stat->freed, -1, out, arg); + mi_print_amount(stat->total, -1, out, arg); + // mi_print_amount(stat->freed, -1, out, arg); mi_print_amount(stat->current, -1, out, arg); if (unit == -1) { _mi_fprintf(out, arg, "%24s", ""); } else { mi_print_amount(-unit, 1, out, arg); - mi_print_count((stat->allocated / -unit), 0, out, arg); + mi_print_count((stat->total / -unit), 0, out, arg); } } - if (stat->allocated > stat->freed) { + if (stat->current != 0) { _mi_fprintf(out, arg, " "); _mi_fprintf(out, arg, (notok == NULL ? "not all freed" : notok)); _mi_fprintf(out, arg, "\n"); @@ -247,7 +230,7 @@ static void mi_stat_print_ex(const mi_stat_count_t* stat, const char* msg, int64 } else { mi_print_amount(stat->peak, 1, out, arg); - mi_print_amount(stat->allocated, 1, out, arg); + mi_print_amount(stat->total, 1, out, arg); _mi_fprintf(out, arg, "%11s", " "); // no freed mi_print_amount(stat->current, 1, out, arg); _mi_fprintf(out, arg, "\n"); @@ -272,7 +255,7 @@ static void mi_stat_counter_print(const mi_stat_counter_t* stat, const char* msg static void mi_stat_counter_print_avg(const mi_stat_counter_t* stat, const char* msg, mi_output_fun* out, void* arg) { - const int64_t avg_tens = (stat->count == 0 ? 0 : (stat->total*10 / stat->count)); + const int64_t avg_tens = (stat->total == 0 ? 0 : (stat->total*10 / stat->total)); const long avg_whole = (long)(avg_tens/10); const long avg_frac1 = (long)(avg_tens%10); _mi_fprintf(out, arg, "%10s: %5ld.%ld avg\n", msg, avg_whole, avg_frac1); @@ -280,7 +263,7 @@ static void mi_stat_counter_print_avg(const mi_stat_counter_t* stat, const char* static void mi_print_header(mi_output_fun* out, void* arg ) { - _mi_fprintf(out, arg, "%10s: %11s %11s %11s %11s %11s %11s\n", "heap stats", "peak ", "total ", "freed ", "current ", "unit ", "count "); + _mi_fprintf(out, arg, "%10s: %11s %11s %11s %11s %11s\n", "heap stats", "peak ", "total ", "current ", "unit ", "total# "); } #if MI_STAT>1 @@ -288,7 +271,7 @@ static void mi_stats_print_bins(const mi_stat_count_t* bins, size_t max, const c bool found = false; char buf[64]; for (size_t i = 0; i <= max; i++) { - if (bins[i].allocated > 0) { + if (bins[i].total > 0) { found = true; int64_t unit = _mi_bin_size((uint8_t)i); _mi_snprintf(buf, 64, "%s %3lu", fmt, (long)i); @@ -352,11 +335,11 @@ static void _mi_stats_print(mi_stats_t* stats, mi_output_fun* out0, void* arg0) mi_stats_print_bins(stats->normal_bins, MI_BIN_HUGE, "normal",out,arg); #endif #if MI_STAT - mi_stat_print(&stats->normal, "normal", (stats->normal_count.count == 0 ? 1 : -(stats->normal.allocated / stats->normal_count.count)), out, arg); - mi_stat_print(&stats->huge, "huge", (stats->huge_count.count == 0 ? 1 : -(stats->huge.allocated / stats->huge_count.count)), out, arg); - mi_stat_count_t total = { 0,0,0,0 }; - mi_stat_add(&total, &stats->normal, 1); - mi_stat_add(&total, &stats->huge, 1); + mi_stat_print(&stats->normal, "normal", (stats->normal_count.total == 0 ? 1 : -1), out, arg); + mi_stat_print(&stats->huge, "huge", (stats->huge_count.total == 0 ? 1 : -1), out, arg); + mi_stat_count_t total = { 0,0,0 }; + mi_stat_add(&total, &stats->normal); + mi_stat_add(&total, &stats->huge); mi_stat_print(&total, "total", 1, out, arg); #endif #if MI_STAT>1