mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-06 23:39:31 +03:00
add debug output for page map; free tld on thread exit
This commit is contained in:
parent
637de624b3
commit
623eaedf33
5 changed files with 55 additions and 18 deletions
|
@ -159,6 +159,7 @@ bool _mi_arena_page_try_reabandon_to_mapped(mi_page_t* page);
|
||||||
// arena-meta.c
|
// arena-meta.c
|
||||||
void* _mi_meta_zalloc( size_t size, mi_memid_t* memid );
|
void* _mi_meta_zalloc( size_t size, mi_memid_t* memid );
|
||||||
void _mi_meta_free(void* p, size_t size, mi_memid_t memid);
|
void _mi_meta_free(void* p, size_t size, mi_memid_t memid);
|
||||||
|
bool _mi_meta_is_meta_page(void* p);
|
||||||
|
|
||||||
// "page-map.c"
|
// "page-map.c"
|
||||||
bool _mi_page_map_init(void);
|
bool _mi_page_map_init(void);
|
||||||
|
|
45
src/arena.c
45
src/arena.c
|
@ -162,6 +162,8 @@ void* mi_arena_area(mi_arena_id_t arena_id, size_t* size) {
|
||||||
static mi_memid_t mi_memid_create_arena(mi_arena_t* arena, size_t slice_index, size_t slice_count) {
|
static mi_memid_t mi_memid_create_arena(mi_arena_t* arena, size_t slice_index, size_t slice_count) {
|
||||||
mi_assert_internal(slice_index < UINT32_MAX);
|
mi_assert_internal(slice_index < UINT32_MAX);
|
||||||
mi_assert_internal(slice_count < UINT32_MAX);
|
mi_assert_internal(slice_count < UINT32_MAX);
|
||||||
|
mi_assert_internal(slice_count > 0);
|
||||||
|
mi_assert_internal(slice_index < arena->slice_count);
|
||||||
mi_memid_t memid = _mi_memid_create(MI_MEM_ARENA);
|
mi_memid_t memid = _mi_memid_create(MI_MEM_ARENA);
|
||||||
memid.mem.arena.arena = arena;
|
memid.mem.arena.arena = arena;
|
||||||
memid.mem.arena.slice_index = (uint32_t)slice_index;
|
memid.mem.arena.slice_index = (uint32_t)slice_index;
|
||||||
|
@ -663,7 +665,8 @@ static mi_page_t* mi_arena_page_alloc_fresh(size_t slice_count, size_t block_siz
|
||||||
page->reserved = (uint16_t)reserved;
|
page->reserved = (uint16_t)reserved;
|
||||||
page->page_start = (uint8_t*)page + block_start;
|
page->page_start = (uint8_t*)page + block_start;
|
||||||
page->block_size = block_size;
|
page->block_size = block_size;
|
||||||
page->memid = memid;
|
page->memid = memid;
|
||||||
|
mi_assert_internal(memid.mem.arena.slice_count > 0);
|
||||||
page->free_is_zero = memid.initially_zero;
|
page->free_is_zero = memid.initially_zero;
|
||||||
if (block_size > 0 && _mi_is_power_of_two(block_size)) {
|
if (block_size > 0 && _mi_is_power_of_two(block_size)) {
|
||||||
page->block_size_shift = (uint8_t)mi_ctz(block_size);
|
page->block_size_shift = (uint8_t)mi_ctz(block_size);
|
||||||
|
@ -1197,7 +1200,33 @@ static size_t mi_debug_show_bfield(mi_bfield_t field, char* buf) {
|
||||||
return bit_set_count;
|
return bit_set_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t mi_debug_show_bitmap(const char* header, size_t slice_count, mi_bitmap_t* bitmap, bool invert) {
|
static size_t mi_debug_show_page_bfield(mi_bfield_t field, char* buf, mi_arena_t* arena, size_t slice_index) {
|
||||||
|
size_t bit_set_count = 0;
|
||||||
|
long bit_of_page = 0;
|
||||||
|
for (int bit = 0; bit < MI_BFIELD_BITS; bit++, bit_of_page--) {
|
||||||
|
bool is_set = ((((mi_bfield_t)1 << bit) & field) != 0);
|
||||||
|
void* start = mi_arena_slice_start(arena, slice_index + bit);
|
||||||
|
if (is_set) {
|
||||||
|
bit_set_count++;
|
||||||
|
mi_page_t* page = (mi_page_t*)start;
|
||||||
|
char c = 'p';
|
||||||
|
if (mi_page_is_abandoned_mapped(page)) { c = 'a'; }
|
||||||
|
else if (mi_page_is_abandoned(page)) { c = 'f'; }
|
||||||
|
bit_of_page = (long)page->memid.mem.arena.slice_count - 1;
|
||||||
|
buf[bit] = c;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
char c = '.';
|
||||||
|
if (bit_of_page > 0) { c = '-'; }
|
||||||
|
else if (_mi_meta_is_meta_page(start)) { c = 'm'; }
|
||||||
|
else if (slice_index + bit < arena->info_slices) { c = 'i'; }
|
||||||
|
buf[bit] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bit_set_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t mi_debug_show_bitmap(const char* header, size_t slice_count, mi_bitmap_t* bitmap, bool invert, mi_arena_t* arena) {
|
||||||
_mi_output_message("%s:\n", header);
|
_mi_output_message("%s:\n", header);
|
||||||
size_t bit_count = 0;
|
size_t bit_count = 0;
|
||||||
size_t bit_set_count = 0;
|
size_t bit_set_count = 0;
|
||||||
|
@ -1217,7 +1246,8 @@ static size_t mi_debug_show_bitmap(const char* header, size_t slice_count, mi_bi
|
||||||
if (bit_count < slice_count) {
|
if (bit_count < slice_count) {
|
||||||
mi_bfield_t bfield = chunk->bfields[j];
|
mi_bfield_t bfield = chunk->bfields[j];
|
||||||
if (invert) bfield = ~bfield;
|
if (invert) bfield = ~bfield;
|
||||||
size_t xcount = mi_debug_show_bfield(bfield, buf + k);
|
size_t xcount = (arena!=NULL ? mi_debug_show_page_bfield(bfield, buf + k, arena, bit_count)
|
||||||
|
: mi_debug_show_bfield(bfield, buf + k));
|
||||||
if (invert) xcount = MI_BFIELD_BITS - xcount;
|
if (invert) xcount = MI_BFIELD_BITS - xcount;
|
||||||
bit_set_count += xcount;
|
bit_set_count += xcount;
|
||||||
k += MI_BFIELD_BITS;
|
k += MI_BFIELD_BITS;
|
||||||
|
@ -1246,15 +1276,16 @@ void mi_debug_show_arenas(bool show_inuse, bool show_abandoned, bool show_purge)
|
||||||
mi_arena_t* arena = mi_atomic_load_ptr_acquire(mi_arena_t, &mi_arenas[i]);
|
mi_arena_t* arena = mi_atomic_load_ptr_acquire(mi_arena_t, &mi_arenas[i]);
|
||||||
if (arena == NULL) break;
|
if (arena == NULL) break;
|
||||||
slice_total += arena->slice_count;
|
slice_total += arena->slice_count;
|
||||||
_mi_output_message("arena %zu: %zu slices (%zu MiB)%s\n", i, arena->slice_count, mi_size_of_slices(arena->slice_count)/MI_MiB, (arena->memid.is_pinned ? ", pinned" : ""));
|
_mi_output_message("arena %zu at %p: %zu slices (%zu MiB)%s\n", i, arena, arena->slice_count, mi_size_of_slices(arena->slice_count)/MI_MiB, (arena->memid.is_pinned ? ", pinned" : ""));
|
||||||
if (show_inuse) {
|
if (show_inuse) {
|
||||||
free_total += mi_debug_show_bitmap("in-use slices", arena->slice_count, arena->slices_free, true);
|
free_total += mi_debug_show_bitmap("in-use slices", arena->slice_count, arena->slices_free, true, NULL);
|
||||||
}
|
}
|
||||||
mi_debug_show_bitmap("committed slices", arena->slice_count, arena->slices_committed, false);
|
mi_debug_show_bitmap("committed slices", arena->slice_count, arena->slices_committed, false, NULL);
|
||||||
// todo: abandoned slices
|
// todo: abandoned slices
|
||||||
if (show_purge) {
|
if (show_purge) {
|
||||||
purge_total += mi_debug_show_bitmap("purgeable slices", arena->slice_count, arena->slices_purge, false);
|
purge_total += mi_debug_show_bitmap("purgeable slices", arena->slice_count, arena->slices_purge, false, NULL);
|
||||||
}
|
}
|
||||||
|
mi_debug_show_bitmap("pages (p=page, a=abandoned, f=full-abandoned, i=info, m=meta)", arena->slice_count, arena->pages, false, arena);
|
||||||
}
|
}
|
||||||
if (show_inuse) _mi_output_message("total inuse slices : %zu\n", slice_total - free_total);
|
if (show_inuse) _mi_output_message("total inuse slices : %zu\n", slice_total - free_total);
|
||||||
// if (show_abandoned) _mi_verbose_message("total abandoned slices: %zu\n", abandoned_total);
|
// if (show_abandoned) _mi_verbose_message("total abandoned slices: %zu\n", abandoned_total);
|
||||||
|
|
13
src/init.c
13
src/init.c
|
@ -398,11 +398,10 @@ static bool _mi_thread_heap_done(mi_heap_t* heap) {
|
||||||
// merge stats
|
// merge stats
|
||||||
_mi_stats_done(&heap->tld->stats);
|
_mi_stats_done(&heap->tld->stats);
|
||||||
|
|
||||||
// free if not the main thread
|
// free heap meta data
|
||||||
if (heap != &_mi_heap_main) {
|
_mi_meta_free(heap, sizeof(mi_heap_t), heap->memid);
|
||||||
_mi_meta_free(heap, sizeof(mi_heap_t), heap->memid);
|
|
||||||
}
|
if (heap == &_mi_heap_main) {
|
||||||
else {
|
|
||||||
#if 0
|
#if 0
|
||||||
// never free the main thread even in debug mode; if a dll is linked statically with mimalloc,
|
// never free the main thread even in debug mode; if a dll is linked statically with mimalloc,
|
||||||
// there may still be delete/free calls after the mi_fls_done is called. Issue #207
|
// there may still be delete/free calls after the mi_fls_done is called. Issue #207
|
||||||
|
@ -410,6 +409,10 @@ static bool _mi_thread_heap_done(mi_heap_t* heap) {
|
||||||
mi_assert_internal(heap->tld->heap_backing == &_mi_heap_main);
|
mi_assert_internal(heap->tld->heap_backing == &_mi_heap_main);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// free the tld
|
||||||
|
mi_tld_t* tld = _mi_tld();
|
||||||
|
_mi_meta_free(_mi_tld(), sizeof(mi_tld_t), tld->memid);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ static bool mi_page_is_valid_init(mi_page_t* page) {
|
||||||
mi_assert_internal(mi_page_block_size(page) > 0);
|
mi_assert_internal(mi_page_block_size(page) > 0);
|
||||||
mi_assert_internal(page->used <= page->capacity);
|
mi_assert_internal(page->used <= page->capacity);
|
||||||
mi_assert_internal(page->capacity <= page->reserved);
|
mi_assert_internal(page->capacity <= page->reserved);
|
||||||
|
|
||||||
// const size_t bsize = mi_page_block_size(page);
|
// const size_t bsize = mi_page_block_size(page);
|
||||||
// uint8_t* start = mi_page_start(page);
|
// uint8_t* start = mi_page_start(page);
|
||||||
//mi_assert_internal(start + page->capacity*page->block_size == page->top);
|
//mi_assert_internal(start + page->capacity*page->block_size == page->top);
|
||||||
|
@ -623,7 +623,7 @@ void _mi_page_init(mi_heap_t* heap, mi_page_t* page) {
|
||||||
#endif
|
#endif
|
||||||
mi_assert_internal(page->block_size_shift == 0 || (mi_page_block_size(page) == ((size_t)1 << page->block_size_shift)));
|
mi_assert_internal(page->block_size_shift == 0 || (mi_page_block_size(page) == ((size_t)1 << page->block_size_shift)));
|
||||||
mi_assert_expensive(mi_page_is_valid_init(page));
|
mi_assert_expensive(mi_page_is_valid_init(page));
|
||||||
|
|
||||||
// initialize an initial free list
|
// initialize an initial free list
|
||||||
mi_page_extend_free(heap,page);
|
mi_page_extend_free(heap,page);
|
||||||
mi_assert(mi_page_immediate_available(page));
|
mi_assert(mi_page_immediate_available(page));
|
||||||
|
|
|
@ -344,12 +344,14 @@ int main(int argc, char** argv) {
|
||||||
#ifndef USE_STD_MALLOC
|
#ifndef USE_STD_MALLOC
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
//mi_debug_show_arenas(true, true, false);
|
//mi_debug_show_arenas(true, true, false);
|
||||||
|
// mi_debug_show_arenas(true, false, false);
|
||||||
mi_collect(true);
|
mi_collect(true);
|
||||||
mi_debug_show_arenas(true,true,false);
|
mi_debug_show_arenas(true, false, false);
|
||||||
#endif
|
#else
|
||||||
// mi_collect(true);
|
mi_collect(false);
|
||||||
// mi_debug_show_arenas(true, true, false);
|
mi_debug_show_arenas(true, true, false);
|
||||||
// mi_stats_print(NULL);
|
// mi_stats_print(NULL);
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
mi_stats_print(NULL); // so we see rss/commit/elapsed
|
mi_stats_print(NULL); // so we see rss/commit/elapsed
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue