mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-06 15:29:31 +03:00
add debug view of arenas
This commit is contained in:
parent
217871cb45
commit
e314699ee0
4 changed files with 49 additions and 5 deletions
|
@ -267,6 +267,7 @@ mi_decl_export int mi_reserve_huge_os_pages_at(size_t pages, int numa_node, size
|
||||||
mi_decl_export int mi_reserve_os_memory(size_t size, bool commit, bool allow_large) mi_attr_noexcept;
|
mi_decl_export int mi_reserve_os_memory(size_t size, bool commit, bool allow_large) mi_attr_noexcept;
|
||||||
mi_decl_export bool mi_manage_os_memory(void* start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node) mi_attr_noexcept;
|
mi_decl_export bool mi_manage_os_memory(void* start, size_t size, bool is_committed, bool is_large, bool is_zero, int numa_node) mi_attr_noexcept;
|
||||||
|
|
||||||
|
mi_decl_export void mi_debug_show_arenas(void) mi_attr_noexcept;
|
||||||
|
|
||||||
// deprecated
|
// deprecated
|
||||||
mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept;
|
mi_decl_export int mi_reserve_huge_os_pages(size_t pages, double max_secs, size_t* pages_reserved) mi_attr_noexcept;
|
||||||
|
|
31
src/arena.c
31
src/arena.c
|
@ -49,7 +49,7 @@ bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* stats);
|
||||||
// Block info: bit 0 contains the `in_use` bit, the upper bits the
|
// Block info: bit 0 contains the `in_use` bit, the upper bits the
|
||||||
// size in count of arena blocks.
|
// size in count of arena blocks.
|
||||||
typedef uintptr_t mi_block_info_t;
|
typedef uintptr_t mi_block_info_t;
|
||||||
#define MI_ARENA_BLOCK_SIZE MI_SEGMENT_SIZE // 8MiB
|
#define MI_ARENA_BLOCK_SIZE (MI_SEGMENT_SIZE) // 8MiB (must be at least MI_SEGMENT_ALIGN)
|
||||||
#define MI_ARENA_MIN_OBJ_SIZE (MI_ARENA_BLOCK_SIZE/2) // 4MiB
|
#define MI_ARENA_MIN_OBJ_SIZE (MI_ARENA_BLOCK_SIZE/2) // 4MiB
|
||||||
#define MI_MAX_ARENAS (64) // not more than 256 (since we use 8 bits in the memid)
|
#define MI_MAX_ARENAS (64) // not more than 256 (since we use 8 bits in the memid)
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ static size_t mi_block_count_of_size(size_t size) {
|
||||||
----------------------------------------------------------- */
|
----------------------------------------------------------- */
|
||||||
static bool mi_arena_alloc(mi_arena_t* arena, size_t blocks, mi_bitmap_index_t* bitmap_idx)
|
static bool mi_arena_alloc(mi_arena_t* arena, size_t blocks, mi_bitmap_index_t* bitmap_idx)
|
||||||
{
|
{
|
||||||
size_t idx = mi_atomic_load_relaxed(&arena->search_idx); // start from last search; ok to be relaxed as the exact start does not matter
|
size_t idx = 0; // mi_atomic_load_relaxed(&arena->search_idx); // start from last search; ok to be relaxed as the exact start does not matter
|
||||||
if (_mi_bitmap_try_find_from_claim_across(arena->blocks_inuse, arena->field_count, idx, blocks, bitmap_idx)) {
|
if (_mi_bitmap_try_find_from_claim_across(arena->blocks_inuse, arena->field_count, idx, blocks, bitmap_idx)) {
|
||||||
mi_atomic_store_relaxed(&arena->search_idx, mi_bitmap_index_field(*bitmap_idx)); // start search from found location next time around
|
mi_atomic_store_relaxed(&arena->search_idx, mi_bitmap_index_field(*bitmap_idx)); // start search from found location next time around
|
||||||
return true;
|
return true;
|
||||||
|
@ -346,6 +346,33 @@ int mi_reserve_os_memory(size_t size, bool commit, bool allow_large) mi_attr_noe
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t mi_debug_show_bitmap(const char* prefix, mi_bitmap_field_t* fields, size_t field_count ) {
|
||||||
|
size_t inuse_count = 0;
|
||||||
|
for (size_t i = 0; i < field_count; i++) {
|
||||||
|
char buf[MI_BITMAP_FIELD_BITS + 1];
|
||||||
|
uintptr_t field = mi_atomic_load_relaxed(&fields[i]);
|
||||||
|
for (size_t bit = 0; bit < MI_BITMAP_FIELD_BITS; bit++) {
|
||||||
|
bool inuse = ((((uintptr_t)1 << bit) & field) != 0);
|
||||||
|
if (inuse) inuse_count++;
|
||||||
|
buf[MI_BITMAP_FIELD_BITS - 1 - bit] = (inuse ? 'x' : '.');
|
||||||
|
}
|
||||||
|
buf[MI_BITMAP_FIELD_BITS] = 0;
|
||||||
|
_mi_verbose_message("%s%s\n", prefix, buf);
|
||||||
|
}
|
||||||
|
return inuse_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mi_debug_show_arenas(void) mi_attr_noexcept {
|
||||||
|
size_t max_arenas = mi_atomic_load_relaxed(&mi_arena_count);
|
||||||
|
for (size_t i = 0; i < max_arenas; i++) {
|
||||||
|
mi_arena_t* arena = mi_atomic_load_ptr_relaxed(mi_arena_t, &mi_arenas[i]);
|
||||||
|
if (arena == NULL) break;
|
||||||
|
size_t inuse_count = 0;
|
||||||
|
_mi_verbose_message("arena %zu: %zu blocks with %zu fields\n", i, arena->block_count, arena->field_count);
|
||||||
|
inuse_count += mi_debug_show_bitmap(" ", arena->blocks_inuse, arena->field_count);
|
||||||
|
_mi_verbose_message(" blocks in use ('x'): %zu\n", inuse_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------
|
/* -----------------------------------------------------------
|
||||||
Reserve a huge page arena.
|
Reserve a huge page arena.
|
||||||
|
|
|
@ -16,6 +16,8 @@ terms of the MIT license. A copy of the license can be found in the file
|
||||||
|
|
||||||
#include "bitmap.h" // atomic bitmap
|
#include "bitmap.h" // atomic bitmap
|
||||||
|
|
||||||
|
//#define MI_CACHE_DISABLE 1
|
||||||
|
|
||||||
#define MI_CACHE_FIELDS (16)
|
#define MI_CACHE_FIELDS (16)
|
||||||
#define MI_CACHE_MAX (MI_BITMAP_FIELD_BITS*MI_CACHE_FIELDS) // 1024 on 64-bit
|
#define MI_CACHE_MAX (MI_BITMAP_FIELD_BITS*MI_CACHE_FIELDS) // 1024 on 64-bit
|
||||||
|
|
||||||
|
@ -39,6 +41,10 @@ static mi_decl_cache_align mi_bitmap_field_t cache_inuse[MI_CACHE_FIELDS]; //
|
||||||
|
|
||||||
mi_decl_noinline void* _mi_segment_cache_pop(size_t size, mi_commit_mask_t* commit_mask, bool* large, bool* is_pinned, bool* is_zero, size_t* memid, mi_os_tld_t* tld)
|
mi_decl_noinline void* _mi_segment_cache_pop(size_t size, mi_commit_mask_t* commit_mask, bool* large, bool* is_pinned, bool* is_zero, size_t* memid, mi_os_tld_t* tld)
|
||||||
{
|
{
|
||||||
|
#ifdef MI_CACHE_DISABLE
|
||||||
|
return NULL;
|
||||||
|
#else
|
||||||
|
|
||||||
// only segment blocks
|
// only segment blocks
|
||||||
if (size != MI_SEGMENT_SIZE) return NULL;
|
if (size != MI_SEGMENT_SIZE) return NULL;
|
||||||
|
|
||||||
|
@ -79,6 +85,7 @@ mi_decl_noinline void* _mi_segment_cache_pop(size_t size, mi_commit_mask_t* comm
|
||||||
mi_assert_internal(_mi_bitmap_is_claimed(cache_inuse, MI_CACHE_FIELDS, 1, bitidx));
|
mi_assert_internal(_mi_bitmap_is_claimed(cache_inuse, MI_CACHE_FIELDS, 1, bitidx));
|
||||||
_mi_bitmap_unclaim(cache_inuse, MI_CACHE_FIELDS, 1, bitidx);
|
_mi_bitmap_unclaim(cache_inuse, MI_CACHE_FIELDS, 1, bitidx);
|
||||||
return p;
|
return p;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static mi_decl_noinline void mi_commit_mask_decommit(mi_commit_mask_t* cmask, void* p, size_t total, mi_stats_t* stats)
|
static mi_decl_noinline void mi_commit_mask_decommit(mi_commit_mask_t* cmask, void* p, size_t total, mi_stats_t* stats)
|
||||||
|
@ -143,6 +150,10 @@ static mi_decl_noinline void mi_segment_cache_purge(mi_os_tld_t* tld)
|
||||||
|
|
||||||
mi_decl_noinline bool _mi_segment_cache_push(void* start, size_t size, size_t memid, mi_commit_mask_t commit_mask, bool is_large, bool is_pinned, mi_os_tld_t* tld)
|
mi_decl_noinline bool _mi_segment_cache_push(void* start, size_t size, size_t memid, mi_commit_mask_t commit_mask, bool is_large, bool is_pinned, mi_os_tld_t* tld)
|
||||||
{
|
{
|
||||||
|
#ifdef MI_CACHE_DISABLE
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
|
||||||
// only for normal segment blocks
|
// only for normal segment blocks
|
||||||
if (size != MI_SEGMENT_SIZE || ((uintptr_t)start % MI_SEGMENT_ALIGN) != 0) return false;
|
if (size != MI_SEGMENT_SIZE || ((uintptr_t)start % MI_SEGMENT_ALIGN) != 0) return false;
|
||||||
|
|
||||||
|
@ -191,6 +202,7 @@ mi_decl_noinline bool _mi_segment_cache_push(void* start, size_t size, size_t me
|
||||||
// make it available
|
// make it available
|
||||||
_mi_bitmap_unclaim((is_large ? cache_available_large : cache_available), MI_CACHE_FIELDS, 1, bitidx);
|
_mi_bitmap_unclaim((is_large ? cache_available_large : cache_available), MI_CACHE_FIELDS, 1, bitidx);
|
||||||
return true;
|
return true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -189,6 +189,7 @@ static void test_stress(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//mi_collect(false);
|
//mi_collect(false);
|
||||||
|
//mi_debug_show_arenas();
|
||||||
#if !defined(NDEBUG) || defined(MI_TSAN)
|
#if !defined(NDEBUG) || defined(MI_TSAN)
|
||||||
if ((n + 1) % 10 == 0) { printf("- iterations left: %3d\n", ITER - (n + 1)); }
|
if ((n + 1) % 10 == 0) { printf("- iterations left: %3d\n", ITER - (n + 1)); }
|
||||||
#endif
|
#endif
|
||||||
|
@ -244,6 +245,8 @@ int main(int argc, char** argv) {
|
||||||
// Run ITER full iterations where half the objects in the transfer buffer survive to the next round.
|
// Run ITER full iterations where half the objects in the transfer buffer survive to the next round.
|
||||||
srand(0x7feb352d);
|
srand(0x7feb352d);
|
||||||
|
|
||||||
|
//mi_reserve_os_memory(512ULL << 20, true, true);
|
||||||
|
|
||||||
#if !defined(NDEBUG) && !defined(USE_STD_MALLOC)
|
#if !defined(NDEBUG) && !defined(USE_STD_MALLOC)
|
||||||
mi_stats_reset();
|
mi_stats_reset();
|
||||||
#endif
|
#endif
|
||||||
|
@ -256,6 +259,7 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
#if !defined(NDEBUG) && !defined(USE_STD_MALLOC)
|
#if !defined(NDEBUG) && !defined(USE_STD_MALLOC)
|
||||||
mi_collect(true);
|
mi_collect(true);
|
||||||
|
//mi_debug_show_arenas();
|
||||||
#endif
|
#endif
|
||||||
#ifndef USE_STD_MALLOC
|
#ifndef USE_STD_MALLOC
|
||||||
mi_stats_print(NULL);
|
mi_stats_print(NULL);
|
||||||
|
|
Loading…
Add table
Reference in a new issue