From 89dc53eca9ed43cb714546301a7d13bf0502ea52 Mon Sep 17 00:00:00 2001 From: githubzilla Date: Mon, 6 May 2024 07:40:42 +0000 Subject: [PATCH] Add mi_heap_page_utilization --- include/mimalloc.h | 3 +++ include/mimalloc/types.h | 2 +- src/alloc.c | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/include/mimalloc.h b/include/mimalloc.h index 51984d8c..3a022fd6 100644 --- a/include/mimalloc.h +++ b/include/mimalloc.h @@ -285,6 +285,9 @@ mi_decl_export bool mi_manage_os_memory(void* start, size_t size, bool is_commit mi_decl_export void mi_debug_show_arenas(void) mi_attr_noexcept; +mi_decl_export bool mi_heap_page_is_underutilized(mi_heap_t* heap, void* p, float ratio) mi_attr_noexcept; +mi_decl_export float mi_heap_page_utilization(mi_heap_t* heap, void* p) mi_attr_noexcept; + // Experimental: heaps associated with specific memory arena's typedef int mi_arena_id_t; mi_decl_export void* mi_arena_area(mi_arena_id_t arena_id, size_t* size); diff --git a/include/mimalloc/types.h b/include/mimalloc/types.h index c6051524..8771fe43 100644 --- a/include/mimalloc/types.h +++ b/include/mimalloc/types.h @@ -85,7 +85,7 @@ terms of the MIT license. A copy of the license can be found in the file // Encoded free lists allow detection of corrupted free lists // and can detect buffer overflows, modify after free, and double `free`s. #if (MI_SECURE>=3 || MI_DEBUG>=1) -#define MI_ENCODE_FREELIST 1 +//#define MI_ENCODE_FREELIST 1 #endif diff --git a/src/alloc.c b/src/alloc.c index fa66a6b3..51469d14 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -1044,6 +1044,44 @@ mi_decl_nodiscard void* mi_new_reallocn(void* p, size_t newcount, size_t size) { } } +float mi_heap_page_utilization(mi_heap_t* heap, void* p) mi_attr_noexcept { + mi_page_t* page = _mi_ptr_page(p); // get the page that this belongs to + + mi_heap_t* page_heap = (mi_heap_t*)(mi_atomic_load_acquire(&(page)->xheap)); + + // the heap id matches and it is not a full page + if (mi_likely(page_heap == heap && page->flags.x.in_full == 0)) { + // first in the list, meaning it's the head of page queue, thus being used for malloc + if (page->prev == NULL) + return 1.0; + + // this page belong to this heap and is not first in the page queue. Lets check its + // utilization. + float ratio = (float)page->used / (float)page->capacity; + mi_assert_internal(ratio <= 1.0); + return ratio; + } + return 1.0; +} + +bool mi_heap_page_is_underutilized(mi_heap_t* heap, void* p, float ratio) mi_attr_noexcept { + mi_page_t* page = _mi_ptr_page(p); // get the page that this belongs to + + mi_heap_t* page_heap = (mi_heap_t*)(mi_atomic_load_acquire(&(page)->xheap)); + + // the heap id matches and it is not a full page + if (mi_likely(page_heap == heap && page->flags.x.in_full == 0)) { + // first in the list, meaning it's the head of page queue, thus being used for malloc + if (page->prev == NULL) + return false; + + // this page belong to this heap and is not first in the page queue. Lets check its + // utilization. + return page->used <= (unsigned)(page->capacity * ratio); + } + return false; +} + // ------------------------------------------------------ // ensure explicit external inline definitions are emitted! // ------------------------------------------------------