diff --git a/ide/vs2017/mimalloc.vcxproj b/ide/vs2017/mimalloc.vcxproj index 4a831722..752cc82a 100644 --- a/ide/vs2017/mimalloc.vcxproj +++ b/ide/vs2017/mimalloc.vcxproj @@ -93,7 +93,7 @@ true true ../../include - MI_DEBUG=3;_MBCS;%(PreprocessorDefinitions); + MI_DEBUG=3;%(PreprocessorDefinitions); Default @@ -110,7 +110,7 @@ true true ../../include - MI_DEBUG=3;_MBCS;%(PreprocessorDefinitions); + MI_DEBUG=3;%(PreprocessorDefinitions); Default @@ -137,7 +137,7 @@ true true ../../include - _MBCS;%(PreprocessorDefinitions);NDEBUG + %(PreprocessorDefinitions);NDEBUG AssemblyAndSourceCode $(IntDir) true @@ -168,7 +168,7 @@ true true ../../include - _MBCS;%(PreprocessorDefinitions);NDEBUG + %(PreprocessorDefinitions);NDEBUG AssemblyAndSourceCode $(IntDir) true diff --git a/include/mimalloc-types.h b/include/mimalloc-types.h index 1d48dbda..27333105 100644 --- a/include/mimalloc-types.h +++ b/include/mimalloc-types.h @@ -373,6 +373,8 @@ typedef struct mi_segment_queue_s { // Segments thread local data typedef struct mi_segments_tld_s { mi_segment_queue_t small_free; // queue of segments with free small pages + size_t count; // current number of segments; + size_t peak_count; // peak number of segments size_t current_size; // current size of all segments size_t peak_size; // peak size of all segments size_t cache_count; // number of segments in the cache diff --git a/src/init.c b/src/init.c index 1b925e89..a62e8a59 100644 --- a/src/init.c +++ b/src/init.c @@ -91,7 +91,7 @@ mi_decl_thread mi_heap_t* _mi_heap_default = (mi_heap_t*)&_mi_heap_empty; static mi_tld_t tld_main = { 0, &_mi_heap_main, - { { NULL, NULL }, 0, 0, 0, 0, {NULL,NULL}, tld_main_stats }, // segments + { { NULL, NULL }, 0, 0, 0, 0, 0, 0, {NULL,NULL}, tld_main_stats }, // segments { 0, NULL, NULL, 0, tld_main_stats }, // os { MI_STATS_NULL } // stats }; diff --git a/src/segment.c b/src/segment.c index 685f57ee..eae33bba 100644 --- a/src/segment.c +++ b/src/segment.c @@ -35,22 +35,6 @@ terms of the MIT license. A copy of the license can be found in the file ----------------------------------------------------------- */ -#if (MI_DEBUG > 1) -static bool mi_segment_is_valid(mi_segment_t* segment) { - mi_assert_internal(segment != NULL); - mi_assert_internal(_mi_ptr_cookie(segment) == segment->cookie); - mi_assert_internal(segment->used <= segment->capacity); - mi_assert_internal(segment->abandoned <= segment->used); - size_t nfree = 0; - for (size_t i = 0; i < segment->capacity; i++) { - if (!segment->pages[i].segment_in_use) nfree++; - } - mi_assert_internal(nfree + segment->used == segment->capacity); - mi_assert_internal(segment->thread_id == _mi_thread_id()); // or 0 - return true; -} -#endif - /* ----------------------------------------------------------- Queue of segments containing free pages ----------------------------------------------------------- */ @@ -121,6 +105,31 @@ static void mi_segment_queue_insert_before(mi_segment_queue_t* queue, mi_segment } +#if (MI_DEBUG > 1) +static size_t mi_segment_pagesize(mi_segment_t* segment) { + return ((size_t)1 << segment->page_shift); +} +static bool mi_segment_is_valid(mi_segment_t* segment) { + mi_assert_internal(segment != NULL); + mi_assert_internal(_mi_ptr_cookie(segment) == segment->cookie); + mi_assert_internal(segment->used <= segment->capacity); + mi_assert_internal(segment->abandoned <= segment->used); + size_t nfree = 0; + for (size_t i = 0; i < segment->capacity; i++) { + if (!segment->pages[i].segment_in_use) nfree++; + } + mi_assert_internal(nfree + segment->used == segment->capacity); + mi_assert_internal(segment->thread_id == _mi_thread_id()); // or 0 + mi_assert_internal(segment->page_kind == MI_PAGE_HUGE || + (mi_segment_pagesize(segment) * segment->capacity == segment->segment_size)); + return true; +} +#endif + +/* ----------------------------------------------------------- + Segment size calculations +----------------------------------------------------------- */ + // Start of the page available memory; can be used on uninitialized pages (only `segment_idx` must be set) uint8_t* _mi_segment_page_start(const mi_segment_t* segment, const mi_page_t* page, size_t block_size, size_t* page_size) { @@ -196,6 +205,8 @@ proves to be too small for certain workloads). static void mi_segments_track_size(long segment_size, mi_segments_tld_t* tld) { if (segment_size>=0) _mi_stat_increase(&tld->stats->segments,1); else _mi_stat_decrease(&tld->stats->segments,1); + tld->count += (segment_size >= 0 ? 1 : -1); + if (tld->count > tld->peak_count) tld->peak_count = tld->count; tld->current_size += segment_size; if (tld->current_size > tld->peak_size) tld->peak_size = tld->current_size; } @@ -725,7 +736,7 @@ static mi_page_t* mi_segment_huge_page_alloc(size_t size, mi_segments_tld_t* tld mi_page_t* _mi_segment_page_alloc(size_t block_size, mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { mi_page_t* page; - if (block_size < MI_SMALL_PAGE_SIZE / 8) + if (block_size <= (MI_SMALL_PAGE_SIZE / 8)) // smaller blocks than 8kb (assuming MI_SMALL_PAGE_SIZE == 64kb) page = mi_segment_small_page_alloc(tld,os_tld); else if (block_size < (MI_LARGE_SIZE_MAX - sizeof(mi_segment_t)))