Skip to content

Commit 9eb09af

Browse files
committed
maintain the total size of the pages in the full queue (issue #1220)
2 parents 35d2e39 + bff836f commit 9eb09af

3 files changed

Lines changed: 20 additions & 4 deletions

File tree

include/mimalloc/internal.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -822,17 +822,29 @@ static inline mi_page_flags_t mi_page_flags(const mi_page_t* page) {
822822
return (mi_page_xthread_id(page) & MI_PAGE_FLAG_MASK);
823823
}
824824

825-
static inline void mi_page_flags_set(mi_page_t* page, bool set, mi_page_flags_t newflag) {
826-
if (set) { mi_atomic_or_relaxed(&page->xthread_id, newflag); }
827-
else { mi_atomic_and_relaxed(&page->xthread_id, ~newflag); }
825+
static inline bool mi_page_flags_set(mi_page_t* page, bool set, mi_page_flags_t newflag) {
826+
mi_page_flags_t old;
827+
if (set) { old = mi_atomic_or_relaxed(&page->xthread_id, newflag); }
828+
else { old = mi_atomic_and_relaxed(&page->xthread_id, ~newflag); }
829+
return ((old & newflag) == newflag);
828830
}
829831

830832
static inline bool mi_page_is_in_full(const mi_page_t* page) {
831833
return ((mi_page_flags(page) & MI_PAGE_IN_FULL_QUEUE) != 0);
832834
}
833835

834836
static inline void mi_page_set_in_full(mi_page_t* page, bool in_full) {
835-
mi_page_flags_set(page, in_full, MI_PAGE_IN_FULL_QUEUE);
837+
const bool was_in_full = mi_page_flags_set(page, in_full, MI_PAGE_IN_FULL_QUEUE);
838+
if (was_in_full != in_full) {
839+
// optimize: maintain pages_full_size to avoid visiting the full queue (issue #1220)
840+
mi_theap_t* const theap = page->theap;
841+
mi_assert_internal(theap!=NULL);
842+
if (theap != NULL) {
843+
const size_t size = page->capacity * mi_page_block_size(page);
844+
if (in_full) { theap->pages_full_size += size; }
845+
else { mi_assert_internal(size <= theap->pages_full_size); theap->pages_full_size -= size; }
846+
}
847+
}
836848
}
837849

838850
static inline bool mi_page_has_interior_pointers(const mi_page_t* page) {

include/mimalloc/types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,7 @@ struct mi_theap_s {
517517
size_t page_count; // total number of pages in the `pages` queues.
518518
size_t page_retired_min; // smallest retired index (retired pages are fully free, but still in the page queues)
519519
size_t page_retired_max; // largest retired index into the `pages` array.
520+
size_t pages_full_size; // optimization: total size of blocks in the pages of the full queue (issue #1220)
520521
long generic_count; // how often is `_mi_malloc_generic` called?
521522
long generic_collect_count; // how often is `_mi_malloc_generic` called without collecting?
522523

src/init.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ mi_decl_cache_align const mi_theap_t _mi_theap_empty = {
126126
{ {0}, {0}, 0, true }, // random
127127
0, // page count
128128
MI_BIN_FULL, 0, // page retired min/max
129+
0, // pages_full_size
129130
0, 0, // generic count
130131
NULL, NULL, // tnext, tprev
131132
NULL, NULL, // hnext, hprev
@@ -150,6 +151,7 @@ mi_decl_cache_align const mi_theap_t _mi_theap_empty_wrong = {
150151
{ {0}, {0}, 0, true }, // random
151152
0, // page count
152153
MI_BIN_FULL, 0, // page retired min/max
154+
0, // pages_full_size
153155
0, 0, // generic count
154156
NULL, NULL, // tnext, tprev
155157
NULL, NULL, // hnext, hprev
@@ -191,6 +193,7 @@ mi_decl_cache_align mi_theap_t theap_main = {
191193
{ {0x846ca68b}, {0}, 0, true }, // random
192194
0, // page count
193195
MI_BIN_FULL, 0, // page retired min/max
196+
0, // pages_full_size
194197
0, 0, // generic count
195198
NULL, NULL, // tnext, tprev
196199
NULL, NULL, // hnext, hprev

0 commit comments

Comments
 (0)