mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-21 06:19:31 +03:00
Merge e5bcfae95f
into 9afdf762a6
This commit is contained in:
commit
cc07ed336b
6 changed files with 96 additions and 1 deletions
|
@ -131,6 +131,8 @@ void _mi_heap_set_default_direct(mi_heap_t* heap);
|
||||||
|
|
||||||
// "stats.c"
|
// "stats.c"
|
||||||
void _mi_stats_done(mi_stats_t* stats);
|
void _mi_stats_done(mi_stats_t* stats);
|
||||||
|
void _mi_histogram_log(size_t size);
|
||||||
|
void _mi_histogram_print(mi_output_fun* out);
|
||||||
|
|
||||||
mi_msecs_t _mi_clock_now(void);
|
mi_msecs_t _mi_clock_now(void);
|
||||||
mi_msecs_t _mi_clock_end(mi_msecs_t start);
|
mi_msecs_t _mi_clock_end(mi_msecs_t start);
|
||||||
|
|
|
@ -304,6 +304,7 @@ typedef enum mi_option_e {
|
||||||
// stable options
|
// stable options
|
||||||
mi_option_show_errors, // print error messages
|
mi_option_show_errors, // print error messages
|
||||||
mi_option_show_stats, // print statistics on termination
|
mi_option_show_stats, // print statistics on termination
|
||||||
|
mi_option_show_histogram, // print histogram
|
||||||
mi_option_verbose, // print verbose messages
|
mi_option_verbose, // print verbose messages
|
||||||
// the following options are experimental (see src/options.h)
|
// the following options are experimental (see src/options.h)
|
||||||
mi_option_eager_commit,
|
mi_option_eager_commit,
|
||||||
|
|
|
@ -98,7 +98,11 @@ extern inline mi_decl_restrict void* mi_malloc_small(size_t size) mi_attr_noexce
|
||||||
// The main allocation function
|
// The main allocation function
|
||||||
extern inline mi_decl_restrict void* mi_heap_malloc(mi_heap_t* heap, size_t size) mi_attr_noexcept {
|
extern inline mi_decl_restrict void* mi_heap_malloc(mi_heap_t* heap, size_t size) mi_attr_noexcept {
|
||||||
if (mi_likely(size <= MI_SMALL_SIZE_MAX)) {
|
if (mi_likely(size <= MI_SMALL_SIZE_MAX)) {
|
||||||
return mi_heap_malloc_small(heap, size);
|
void *p = mi_heap_malloc_small(heap, size);
|
||||||
|
#if MI_STAT>1
|
||||||
|
if (p) { _mi_histogram_log(size); }
|
||||||
|
#endif
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mi_assert(heap!=NULL);
|
mi_assert(heap!=NULL);
|
||||||
|
@ -106,6 +110,9 @@ extern inline mi_decl_restrict void* mi_heap_malloc(mi_heap_t* heap, size_t size
|
||||||
void* const p = _mi_malloc_generic(heap, size + MI_PADDING_SIZE); // note: size can overflow but it is detected in malloc_generic
|
void* const p = _mi_malloc_generic(heap, size + MI_PADDING_SIZE); // note: size can overflow but it is detected in malloc_generic
|
||||||
mi_assert_internal(p == NULL || mi_usable_size(p) >= size);
|
mi_assert_internal(p == NULL || mi_usable_size(p) >= size);
|
||||||
#if MI_STAT>1
|
#if MI_STAT>1
|
||||||
|
if (p) { _mi_histogram_log(size); }
|
||||||
|
#endif
|
||||||
|
#if MI_STAT>1
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
if (!mi_heap_is_initialized(heap)) { heap = mi_get_default_heap(); }
|
if (!mi_heap_is_initialized(heap)) { heap = mi_get_default_heap(); }
|
||||||
mi_heap_stat_increase(heap, malloc, mi_usable_size(p));
|
mi_heap_stat_increase(heap, malloc, mi_usable_size(p));
|
||||||
|
|
|
@ -603,6 +603,11 @@ static void mi_process_done(void) {
|
||||||
if (mi_option_is_enabled(mi_option_show_stats) || mi_option_is_enabled(mi_option_verbose)) {
|
if (mi_option_is_enabled(mi_option_show_stats) || mi_option_is_enabled(mi_option_verbose)) {
|
||||||
mi_stats_print(NULL);
|
mi_stats_print(NULL);
|
||||||
}
|
}
|
||||||
|
#if MI_STAT>1
|
||||||
|
if (mi_option_is_enabled(mi_option_show_histogram)) {
|
||||||
|
_mi_histogram_print(NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
mi_allocator_done();
|
mi_allocator_done();
|
||||||
_mi_verbose_message("process done: 0x%zx\n", _mi_heap_main.thread_id);
|
_mi_verbose_message("process done: 0x%zx\n", _mi_heap_main.thread_id);
|
||||||
os_preloading = true; // don't call the C runtime anymore
|
os_preloading = true; // don't call the C runtime anymore
|
||||||
|
|
|
@ -63,6 +63,7 @@ static mi_option_desc_t options[_mi_option_last] =
|
||||||
{ 0, UNINIT, MI_OPTION(show_errors) },
|
{ 0, UNINIT, MI_OPTION(show_errors) },
|
||||||
#endif
|
#endif
|
||||||
{ 0, UNINIT, MI_OPTION(show_stats) },
|
{ 0, UNINIT, MI_OPTION(show_stats) },
|
||||||
|
{ 0, UNINIT, MI_OPTION(show_histogram) },
|
||||||
{ 0, UNINIT, MI_OPTION(verbose) },
|
{ 0, UNINIT, MI_OPTION(verbose) },
|
||||||
|
|
||||||
// the following options are experimental and not all combinations make sense.
|
// the following options are experimental and not all combinations make sense.
|
||||||
|
|
79
src/stats.c
79
src/stats.c
|
@ -451,6 +451,85 @@ mi_msecs_t _mi_clock_end(mi_msecs_t start) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------
|
||||||
|
Histogram of allocations sizes (power of 2)
|
||||||
|
----------------------------------------------------------- */
|
||||||
|
|
||||||
|
static _Atomic(size_t) mi_hist[MI_SIZE_BITS] = { 0 };
|
||||||
|
|
||||||
|
void _mi_histogram_log(size_t size)
|
||||||
|
{
|
||||||
|
if (mi_unlikely(size == 0)) return;
|
||||||
|
size_t bucket = mi_bsr(size);
|
||||||
|
mi_atomic_increment_relaxed(mi_hist + bucket);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* _mi_make_bar(char *buf, size_t buflen, size_t value, size_t max, size_t width)
|
||||||
|
{
|
||||||
|
/* we can't dynamically detect if the terminal supports unicode block characters */
|
||||||
|
#if defined(_WIN32)
|
||||||
|
size_t v = value * width / max;
|
||||||
|
buf[0] = '\0';
|
||||||
|
while (v > 0) {
|
||||||
|
strncat(buf, "*", buflen--);
|
||||||
|
v--;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static const char* a[] = { " ", "▏", "▎", "▍", "▌", "▋", "▊", "▉", "█" };
|
||||||
|
size_t v = value * width * 8 / max;
|
||||||
|
buf[0] = '\0';
|
||||||
|
while (v > 8) {
|
||||||
|
strncat(buf, a[8], buflen--);
|
||||||
|
v-=8;
|
||||||
|
}
|
||||||
|
strncat(buf, a[v], buflen--);
|
||||||
|
#endif
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* _mi_format_bytes(char *buf, size_t buflen, size_t count)
|
||||||
|
{
|
||||||
|
#if MI_SIZE_BITS > 32
|
||||||
|
if (count & ~((((size_t)1) << 50) - (size_t)1)) {
|
||||||
|
snprintf(buf, buflen, "%zuPiB", (count+1) >> 50);
|
||||||
|
} else
|
||||||
|
if (count & ~((((size_t)1) << 40) - (size_t)1)) {
|
||||||
|
snprintf(buf, buflen, "%zuTiB", (count+1) >> 40);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
if (count & ~((((size_t)1) << 30) - (size_t)1)) {
|
||||||
|
snprintf(buf, buflen, "%zuGiB", (count+1) >> 30);
|
||||||
|
} else
|
||||||
|
if (count & ~((((size_t)1) << 20) - (size_t)1)) {
|
||||||
|
snprintf(buf, buflen, "%zuMiB", (count+1) >> 20);
|
||||||
|
} else
|
||||||
|
if (count & ~((((size_t)1) << 10) - (size_t)1)) {
|
||||||
|
snprintf(buf, buflen, "%zuKiB", (count+1) >> 10);
|
||||||
|
} else {
|
||||||
|
snprintf(buf, buflen, "%zuB", count);
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _mi_histogram_print(mi_output_fun* out)
|
||||||
|
{
|
||||||
|
#define _NCOLS 50
|
||||||
|
char bar[_NCOLS*3+1], num1[16], num2[16];
|
||||||
|
size_t max_allocs = 0;
|
||||||
|
for (size_t i = 0; i < MI_SIZE_BITS; i++) {
|
||||||
|
if (mi_hist[i] > max_allocs) { max_allocs = mi_hist[i]; }
|
||||||
|
}
|
||||||
|
_mi_fputs(out, NULL, NULL, "\nhistogram of allocation sizes\n");
|
||||||
|
for (size_t i = 0; i < MI_SIZE_BITS; i++) {
|
||||||
|
if (mi_hist[i]) {
|
||||||
|
_mi_fprintf(out, NULL, "%9s - %-9s [ %-9zu ] %s\n",
|
||||||
|
_mi_format_bytes(num1, sizeof(num1), ((size_t)1 << i)),
|
||||||
|
_mi_format_bytes(num2, sizeof(num2), ((size_t)1 << (i+1))-1),
|
||||||
|
mi_hist[i], _mi_make_bar(bar, sizeof(bar), mi_hist[i], max_allocs, _NCOLS));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
// Basic process statistics
|
// Basic process statistics
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
|
|
Loading…
Add table
Reference in a new issue