From 18174400b238d21ac262ade28a7461f385c200be Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Sat, 1 Mar 2025 18:04:34 -0800 Subject: [PATCH 1/3] fix stats_add condition --- src/stats.c | 23 +++++++++++------------ test/test-stress.c | 8 +++++--- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/stats.c b/src/stats.c index 1f3b928c..1edd89b1 100644 --- a/src/stats.c +++ b/src/stats.c @@ -38,10 +38,8 @@ static void mi_stat_update(mi_stat_count_t* stat, int64_t amount) { else { // add thread local stat->current += amount; - if (stat->current > stat->peak) stat->peak = stat->current; - if (amount > 0) { - stat->total += amount; - } + if (stat->current > stat->peak) { stat->peak = stat->current; } + if (amount > 0) { stat->total += amount; } } } @@ -67,16 +65,17 @@ void _mi_stat_decrease(mi_stat_count_t* stat, size_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) { if (stat==src) return; - if (src->total==0) return; - mi_atomic_addi64_relaxed( &stat->total, src->total); - mi_atomic_addi64_relaxed( &stat->current, src->current); + if (src->total!=0) { mi_atomic_addi64_relaxed(&stat->total, src->total); } + if (src->current!=0) { 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); + if (src->peak > stat->peak) { + 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) { if (stat==src) return; - mi_atomic_addi64_relaxed( &stat->total, src->total); + if (src->total!=0) { mi_atomic_addi64_relaxed(&stat->total, src->total); } } // must be thread safe as it is called from stats_merge @@ -113,9 +112,9 @@ static void mi_stats_add(mi_stats_t* stats, const mi_stats_t* src) { mi_stat_counter_add(&stats->guarded_alloc_count, &src->guarded_alloc_count); #if MI_STAT>1 for (size_t i = 0; i <= MI_BIN_HUGE; i++) { - if (src->normal_bins[i].total > 0) { - mi_stat_add(&stats->normal_bins[i], &src->normal_bins[i]); - } + // if (src->normal_bins[i].total != 0 && src->normal_bins[i].current != 0) { + mi_stat_add(&stats->normal_bins[i], &src->normal_bins[i]); + //} } #endif } diff --git a/test/test-stress.c b/test/test-stress.c index d23c7461..41f2162b 100644 --- a/test/test-stress.c +++ b/test/test-stress.c @@ -285,9 +285,6 @@ int main(int argc, char** argv) { #if !defined(NDEBUG) && !defined(USE_STD_MALLOC) mi_option_set(mi_option_arena_reserve, 32 * 1024 /* in kib = 32MiB */); #endif - #ifndef USE_STD_MALLOC - mi_stats_reset(); - #endif // > mimalloc-test-stress [THREADS] [SCALE] [ITER] if (argc >= 2) { @@ -309,6 +306,11 @@ int main(int argc, char** argv) { allow_large_objects = true; } printf("Using %d threads with a %d%% load-per-thread and %d iterations %s\n", THREADS, SCALE, ITER, (allow_large_objects ? "(allow large objects)" : "")); + + #if !defined(NDEBUG) && !defined(USE_STD_MALLOC) + mi_stats_reset(); + #endif + //mi_reserve_os_memory(1024*1024*1024ULL, false, true); //int res = mi_reserve_huge_os_pages(4,1); //printf("(reserve huge: %i\n)", res); From 4d727ee6e62b726b22f0fe06866a1501ceb3a0bd Mon Sep 17 00:00:00 2001 From: daanx Date: Sat, 1 Mar 2025 18:30:24 -0800 Subject: [PATCH 2/3] avoid pthread allocation size in mstress bench --- test/test-stress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test-stress.c b/test/test-stress.c index 41f2162b..c41954d3 100644 --- a/test/test-stress.c +++ b/test/test-stress.c @@ -116,7 +116,7 @@ static void* alloc_items(size_t items, random_t r) { else if (chance(10, r) && allow_large_objects) items *= 1000; // 0.1% huge else items *= 100; // 1% large objects; } - if (items == 40) items++; // pthreads uses that size for stack increases + if (items>=32 && items<=40) items*=2; // pthreads uses 320b allocations (this shows that more clearly in the stats) if (use_one_size > 0) items = (use_one_size / sizeof(uintptr_t)); if (items==0) items = 1; uintptr_t* p = (uintptr_t*)custom_calloc(items,sizeof(uintptr_t)); From bc5f636c5e010f4ad8da638af33a58722811ab25 Mon Sep 17 00:00:00 2001 From: Daan Leijen Date: Sat, 1 Mar 2025 19:46:01 -0800 Subject: [PATCH 3/3] nicer stats --- src/segment.c | 6 +++--- src/stats.c | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/segment.c b/src/segment.c index 27a3f295..e2730b7f 100644 --- a/src/segment.c +++ b/src/segment.c @@ -652,7 +652,7 @@ static mi_segment_t* mi_segment_alloc(size_t required, mi_page_kind_t page_kind, static void mi_segment_free(mi_segment_t* segment, bool force, mi_segments_tld_t* tld) { MI_UNUSED(force); mi_assert(segment != NULL); - + // in `mi_segment_force_abandon` we set this to true to ensure the segment's memory stays valid if (segment->dont_free) return; @@ -664,7 +664,7 @@ static void mi_segment_free(mi_segment_t* segment, bool force, mi_segments_tld_t mi_assert_expensive(!mi_segment_queue_contains(&tld->medium_free, segment)); mi_assert(segment->next == NULL); mi_assert(segment->prev == NULL); - _mi_stat_decrease(&tld->stats->page_committed, segment->segment_info_size); + // _mi_stat_decrease(&tld->stats->page_committed, segment->segment_info_size); // return it to the OS mi_segment_os_free(segment, segment->segment_size, tld); @@ -1062,7 +1062,7 @@ static void mi_segment_force_abandon(mi_segment_t* segment, mi_segments_tld_t* t { mi_assert_internal(segment->abandoned < segment->used); mi_assert_internal(!segment->dont_free); - + // ensure the segment does not get free'd underneath us (so we can check if a page has been freed in `mi_page_force_abandon`) segment->dont_free = true; diff --git a/src/stats.c b/src/stats.c index 1edd89b1..c4ec92de 100644 --- a/src/stats.c +++ b/src/stats.c @@ -69,7 +69,7 @@ static void mi_stat_add(mi_stat_count_t* stat, const mi_stat_count_t* src) { if (src->current!=0) { mi_atomic_addi64_relaxed(&stat->current, src->current); } // peak scores do really not work across threads ... we use conservative max if (src->peak > stat->peak) { - mi_atomic_maxi64_relaxed(&stat->peak, src->peak); // or: mi_atomic_addi64_relaxed( &stat->peak, src->peak); + mi_atomic_maxi64_relaxed(&stat->peak, src->peak); // or: mi_atomic_addi64_relaxed( &stat->peak, src->peak); } } @@ -108,7 +108,7 @@ static void mi_stats_add(mi_stats_t* stats, const mi_stats_t* src) { 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->huge_count, &src->huge_count); mi_stat_counter_add(&stats->guarded_alloc_count, &src->guarded_alloc_count); #if MI_STAT>1 for (size_t i = 0; i <= MI_BIN_HUGE; i++) { @@ -305,21 +305,21 @@ static void _mi_stats_print(mi_stats_t* stats, mi_output_fun* out0, void* arg0) #endif #if MI_STAT 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_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); + mi_stat_print_ex(&total, "total", 1, out, arg, ""); #endif #if MI_STAT>1 - mi_stat_print(&stats->malloc, "malloc req", 1, out, arg); + mi_stat_print_ex(&stats->malloc, "malloc req", 1, out, arg, ""); _mi_fprintf(out, arg, "\n"); #endif mi_stat_print_ex(&stats->reserved, "reserved", 1, out, arg, ""); mi_stat_print_ex(&stats->committed, "committed", 1, out, arg, ""); mi_stat_peak_print(&stats->reset, "reset", 1, out, arg ); mi_stat_peak_print(&stats->purged, "purged", 1, out, arg ); - mi_stat_print(&stats->page_committed, "touched", 1, out, arg); + mi_stat_print_ex(&stats->page_committed, "touched", 1, out, arg, ""); mi_stat_print(&stats->segments, "segments", -1, out, arg); mi_stat_print(&stats->segments_abandoned, "-abandoned", -1, out, arg); mi_stat_print(&stats->segments_cache, "-cached", -1, out, arg); @@ -445,7 +445,7 @@ mi_decl_export void mi_process_info(size_t* elapsed_msecs, size_t* user_msecs, s pinfo.page_faults = 0; _mi_prim_process_info(&pinfo); - + if (elapsed_msecs!=NULL) *elapsed_msecs = (pinfo.elapsed < 0 ? 0 : (pinfo.elapsed < (mi_msecs_t)PTRDIFF_MAX ? (size_t)pinfo.elapsed : PTRDIFF_MAX)); if (user_msecs!=NULL) *user_msecs = (pinfo.utime < 0 ? 0 : (pinfo.utime < (mi_msecs_t)PTRDIFF_MAX ? (size_t)pinfo.utime : PTRDIFF_MAX)); if (system_msecs!=NULL) *system_msecs = (pinfo.stime < 0 ? 0 : (pinfo.stime < (mi_msecs_t)PTRDIFF_MAX ? (size_t)pinfo.stime : PTRDIFF_MAX));