diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f880f74..bc4b3a51 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,7 +176,7 @@ endif() # Compiler flags if(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU") - list(APPEND mi_cflags -Wall -Wextra -Wno-unknown-pragmas -fvisibility=hidden) + list(APPEND mi_cflags -Wall -Wextra -Wno-unknown-pragmas -fvisibility=hidden $<$:-O3>) if(NOT MI_USE_CXX) list(APPEND mi_cflags -Wstrict-prototypes) endif() diff --git a/include/mimalloc-internal.h b/include/mimalloc-internal.h index 4e05c724..12d050f7 100644 --- a/include/mimalloc-internal.h +++ b/include/mimalloc-internal.h @@ -497,6 +497,10 @@ static inline size_t mi_segment_size(mi_segment_t* segment) { return segment->segment_slices * MI_SEGMENT_SLICE_SIZE; } +static inline uint8_t* mi_segment_end(mi_segment_t* segment) { + return (uint8_t*)segment + mi_segment_size(segment); +} + // Thread free access static inline mi_block_t* mi_page_thread_free(const mi_page_t* page) { return (mi_block_t*)(mi_atomic_load_relaxed(&((mi_page_t*)page)->xthread_free) & ~3); diff --git a/src/options.c b/src/options.c index 925ecbf9..859b3871 100644 --- a/src/options.c +++ b/src/options.c @@ -66,7 +66,7 @@ static mi_option_desc_t options[_mi_option_last] = { 0, UNINIT, MI_OPTION(verbose) }, // the following options are experimental and not all combinations make sense. - { 0, UNINIT, MI_OPTION(eager_commit) }, // commit per segment directly (8MiB) (but see also `eager_commit_delay`) + { 1, UNINIT, MI_OPTION(eager_commit) }, // commit per segment directly (8MiB) (but see also `eager_commit_delay`) #if defined(_WIN32) || (MI_INTPTR_SIZE <= 4) // and other OS's without overcommit? { 0, UNINIT, MI_OPTION(eager_region_commit) }, { 0, UNINIT, MI_OPTION(reset_decommits) }, // reset decommits memory @@ -89,7 +89,7 @@ static mi_option_desc_t options[_mi_option_last] = { 1, UNINIT, MI_OPTION(eager_commit_delay) }, // the first N segments per thread are not eagerly committed (but per page in the segment on demand) #endif { 1, UNINIT, MI_OPTION(allow_decommit) }, // decommit slices when no longer used (after reset_delay milli-seconds) - { 100, UNINIT, MI_OPTION(reset_delay) }, // page reset delay in milli-seconds (= decommit) + { 25, UNINIT, MI_OPTION(reset_delay) }, // page reset delay in milli-seconds (= decommit) { 500, UNINIT, MI_OPTION(segment_decommit_delay) },// decommit delay in milli-seconds for freed segments { 0, UNINIT, MI_OPTION(use_numa_nodes) }, // 0 = use available numa nodes, otherwise use at most N nodes. { 0, UNINIT, MI_OPTION(limit_os_alloc) }, // 1 = do not use OS memory for allocation (but only reserved arenas) diff --git a/src/segment.c b/src/segment.c index 93548f24..a80ae9c4 100644 --- a/src/segment.c +++ b/src/segment.c @@ -448,7 +448,8 @@ static void mi_segment_commit_mask(mi_segment_t* segment, bool conservative, uin mi_assert_internal(_mi_ptr_segment(p) == segment); mi_commit_mask_create_empty(cm); if (size == 0 || size > MI_SEGMENT_SIZE) return; - if (p >= (uint8_t*)segment + mi_segment_size(segment)) return; + const ptrdiff_t segsize = (ptrdiff_t)mi_segment_size(segment); + if (p >= (uint8_t*)segment + segsize) return; ptrdiff_t diff = (p - (uint8_t*)segment); ptrdiff_t start; @@ -461,6 +462,10 @@ static void mi_segment_commit_mask(mi_segment_t* segment, bool conservative, uin start = _mi_aligni_down(diff, MI_COMMIT_SIZE); end = _mi_aligni_up(diff + size, MI_COMMIT_SIZE); } + mi_assert_internal(end <= segsize); + if (end > segsize) { + end = segsize; + } mi_assert_internal(start % MI_COMMIT_SIZE==0 && end % MI_COMMIT_SIZE == 0); *start_p = (uint8_t*)segment + start; @@ -478,9 +483,14 @@ static void mi_segment_commit_mask(mi_segment_t* segment, bool conservative, uin mi_commit_mask_create(bitidx, bitcount, cm); } +#define MI_COMMIT_SIZE_BATCH MiB + static bool mi_segment_commitx(mi_segment_t* segment, bool commit, uint8_t* p, size_t size, mi_stats_t* stats) { mi_assert_internal(mi_commit_mask_all_set(&segment->commit_mask, &segment->decommit_mask)); + //if (commit && size < MI_COMMIT_SIZE_BATCH && p + MI_COMMIT_SIZE_BATCH <= mi_segment_end(segment)) { + // size = MI_COMMIT_SIZE_BATCH; + // } // commit liberal, but decommit conservative uint8_t* start = NULL; size_t full_size = 0; @@ -541,6 +551,21 @@ static void mi_segment_perhaps_decommit(mi_segment_t* segment, uint8_t* p, size_ mi_commit_mask_create_intersect(&segment->commit_mask, &mask, &cmask); // only decommit what is committed; span_free may try to decommit more mi_commit_mask_set(&segment->decommit_mask, &cmask); segment->decommit_expire = _mi_clock_now() + mi_option_get(mi_option_reset_delay); + mi_msecs_t now = _mi_clock_now(); + if (segment->decommit_expire == 0) { + // no previous decommits, initialize now + mi_assert_internal(mi_commit_mask_is_empty(&segment->decommit_mask)); + segment->decommit_expire = now + mi_option_get(mi_option_reset_delay); + } + else if (segment->decommit_expire <= now) { + // previous decommit mask already expired + // mi_segment_delayed_decommit(segment, true, stats); + segment->decommit_expire = now + 1; + } + else { + // previous decommit mask is not yet expired + // segment->decommit_expire++; + } } }