add mi_stats_get_bin_size and chunk counters
diff --git a/include/mimalloc-stats.h b/include/mimalloc-stats.h index 44c4886..93b728b 100644 --- a/include/mimalloc-stats.h +++ b/include/mimalloc-stats.h
@@ -11,7 +11,7 @@ #include <mimalloc.h> #include <stdint.h> -#define MI_STAT_VERSION 1 // increased on every backward incompatible change +#define MI_STAT_VERSION 2 // increased on every backward incompatible change // count allocation over time typedef struct mi_stat_count_s { @@ -65,6 +65,17 @@ MI_STAT_COUNTER(pages_unabandon_busy_wait) \ +// Size bins for chunks +typedef enum mi_bbin_e { + MI_BBIN_SMALL, // slice_count == 1 + MI_BBIN_OTHER, // slice_count: any other from the other bins, and 1 <= slice_count <= MI_BCHUNK_BITS + MI_BBIN_MEDIUM, // slice_count == 8 + MI_BBIN_LARGE, // slice_count == MI_SIZE_BITS (only used if MI_ENABLE_LARGE_PAGES is 1) + MI_BBIN_NONE, // no bin assigned yet (the chunk is completely free) + MI_BBIN_COUNT +} mi_bbin_t; + + // Define the statistics structure #define MI_BIN_HUGE (73U) // see types.h #define MI_STAT_COUNT(stat) mi_stat_count_t stat; @@ -83,6 +94,7 @@ // size segregated statistics mi_stat_count_t malloc_bins[MI_BIN_HUGE+1]; // allocation per size bin mi_stat_count_t page_bins[MI_BIN_HUGE+1]; // pages allocated per size bin + mi_stat_count_t chunk_bins[MI_BBIN_COUNT]; // chunks per page sizes } mi_stats_t; #undef MI_STAT_COUNT @@ -93,8 +105,9 @@ extern "C" { #endif -mi_decl_export void mi_stats_get( size_t stats_size, mi_stats_t* stats ) mi_attr_noexcept; -mi_decl_export char* mi_stats_get_json( size_t buf_size, char* buf ) mi_attr_noexcept; // use mi_free to free the result if the input buf == NULL +mi_decl_export void mi_stats_get( size_t stats_size, mi_stats_t* stats ) mi_attr_noexcept; +mi_decl_export char* mi_stats_get_json( size_t buf_size, char* buf ) mi_attr_noexcept; // use mi_free to free the result if the input buf == NULL +mi_decl_export size_t mi_stats_get_bin_size(size_t bin) mi_attr_noexcept; #ifdef __cplusplus }
diff --git a/include/mimalloc/internal.h b/include/mimalloc/internal.h index 8a880b8..f57f108 100644 --- a/include/mimalloc/internal.h +++ b/include/mimalloc/internal.h
@@ -299,7 +299,9 @@ #define MI_INIT64(x) MI_INIT32(x),MI_INIT32(x) #define MI_INIT128(x) MI_INIT64(x),MI_INIT64(x) #define MI_INIT256(x) MI_INIT128(x),MI_INIT128(x) + #define MI_INIT74(x) MI_INIT64(x),MI_INIT8(x),x(),x() +#define MI_INIT5(x) MI_INIT4(x),x() #include <string.h> // initialize a local variable to zero; use memset as compilers optimize constant sized memset's
diff --git a/src/bitmap.c b/src/bitmap.c index f7f94dd..f010a42 100644 --- a/src/bitmap.c +++ b/src/bitmap.c
@@ -1415,10 +1415,12 @@ mi_assert_internal(chunk_idx < mi_bbitmap_chunk_count(bbitmap)); for (mi_bbin_t ibin = MI_BBIN_SMALL; ibin < MI_BBIN_NONE; ibin = mi_bbin_inc(ibin)) { if (ibin == bin) { - mi_bchunk_set(& bbitmap->chunkmap_bins[ibin], chunk_idx, NULL); + const bool was_clear = mi_bchunk_set(& bbitmap->chunkmap_bins[ibin], chunk_idx, NULL); + if (was_clear) { mi_os_stat_increase(chunk_bins[ibin],1); } } else { - mi_bchunk_clear(&bbitmap->chunkmap_bins[ibin], chunk_idx, NULL); + const bool was_set = mi_bchunk_clear(&bbitmap->chunkmap_bins[ibin], chunk_idx, NULL); + if (was_set) { mi_os_stat_decrease(chunk_bins[ibin],1); } } } }
diff --git a/src/bitmap.h b/src/bitmap.h index 0237d00..83af74e 100644 --- a/src/bitmap.h +++ b/src/bitmap.h
@@ -212,16 +212,7 @@ much fragmentation since we keep chunks for larger blocks separate. ---------------------------------------------------------------------------- */ -// Size bins; larger bins are allowed to go into smaller bins. -// SMALL can only be in small (and NONE), so they cannot fragment the larger bins. -typedef enum mi_bbin_e { - MI_BBIN_SMALL, // slice_count == 1 - MI_BBIN_OTHER, // slice_count: any other from the other bins, and 1 <= slice_count <= MI_BCHUNK_BITS - MI_BBIN_MEDIUM, // slice_count == 8 - MI_BBIN_LARGE, // slice_count == MI_BFIELD_BITS -- only used if MI_ENABLE_LARGE_PAGES is 1 - MI_BBIN_NONE, // no bin assigned yet (the chunk is completely free) - MI_BBIN_COUNT -} mi_bbin_t; +// mi_bbin_t is defined in mimalloc-stats.h static inline mi_bbin_t mi_bbin_inc(mi_bbin_t bbin) { mi_assert_internal(bbin < MI_BBIN_COUNT);
diff --git a/src/init.c b/src/init.c index 54905dc..6d4ce65 100644 --- a/src/init.c +++ b/src/init.c
@@ -83,7 +83,8 @@ { { 0 }, { 0 }, { 0 }, { 0 } }, \ \ { MI_INIT74(MI_STAT_COUNT_NULL) }, \ - { MI_INIT74(MI_STAT_COUNT_NULL) } + { MI_INIT74(MI_STAT_COUNT_NULL) }, \ + { MI_INIT5(MI_STAT_COUNT_NULL) } // -------------------------------------------------------- // Statically allocate an empty heap as the initial
diff --git a/src/page-queue.c b/src/page-queue.c index 4c30c97..3e2315c 100644 --- a/src/page-queue.c +++ b/src/page-queue.c
@@ -106,6 +106,7 @@ } size_t _mi_bin_size(size_t bin) { + mi_assert_internal(bin <= MI_BIN_HUGE); return _mi_heap_empty.pages[bin].block_size; }
diff --git a/src/stats.c b/src/stats.c index 27dc69d..7a761d8 100644 --- a/src/stats.c +++ b/src/stats.c
@@ -479,6 +479,11 @@ // Return statistics // -------------------------------------------------------- +size_t mi_stats_get_bin_size(size_t bin) mi_attr_noexcept { + if (bin > MI_BIN_HUGE) return 0; + return _mi_bin_size(bin); +} + void mi_stats_get(size_t stats_size, mi_stats_t* stats) mi_attr_noexcept { if (stats == NULL || stats_size == 0) return; _mi_memzero(stats, stats_size); @@ -529,7 +534,7 @@ } static void mi_heap_buf_print_count_bin(mi_heap_buf_t* hbuf, const char* prefix, mi_stat_count_t* stat, size_t bin, bool add_comma) { - const size_t binsize = _mi_bin_size(bin); + const size_t binsize = mi_stats_get_bin_size(bin); const size_t pagesize = (binsize <= MI_SMALL_MAX_OBJ_SIZE ? MI_SMALL_PAGE_SIZE : (binsize <= MI_MEDIUM_MAX_OBJ_SIZE ? MI_MEDIUM_PAGE_SIZE : (binsize <= MI_LARGE_MAX_OBJ_SIZE ? MI_LARGE_PAGE_SIZE : 0)));