We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
2 parents 35d2e39 + bff836f commit 9eb09afCopy full SHA for 9eb09af
3 files changed
include/mimalloc/internal.h
@@ -822,17 +822,29 @@ static inline mi_page_flags_t mi_page_flags(const mi_page_t* page) {
822
return (mi_page_xthread_id(page) & MI_PAGE_FLAG_MASK);
823
}
824
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); }
+static inline bool mi_page_flags_set(mi_page_t* page, bool set, mi_page_flags_t newflag) {
+ mi_page_flags_t old;
+ 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);
830
831
832
static inline bool mi_page_is_in_full(const mi_page_t* page) {
833
return ((mi_page_flags(page) & MI_PAGE_IN_FULL_QUEUE) != 0);
834
835
836
static inline void mi_page_set_in_full(mi_page_t* page, bool in_full) {
- 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
848
849
850
static inline bool mi_page_has_interior_pointers(const mi_page_t* page) {
include/mimalloc/types.h
@@ -517,6 +517,7 @@ struct mi_theap_s {
517
size_t page_count; // total number of pages in the `pages` queues.
518
size_t page_retired_min; // smallest retired index (retired pages are fully free, but still in the page queues)
519
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)
521
long generic_count; // how often is `_mi_malloc_generic` called?
522
long generic_collect_count; // how often is `_mi_malloc_generic` called without collecting?
523
src/init.c
@@ -126,6 +126,7 @@ mi_decl_cache_align const mi_theap_t _mi_theap_empty = {
126
{ {0}, {0}, 0, true }, // random
127
0, // page count
128
MI_BIN_FULL, 0, // page retired min/max
129
+ 0, // pages_full_size
130
0, 0, // generic count
131
NULL, NULL, // tnext, tprev
132
NULL, NULL, // hnext, hprev
@@ -150,6 +151,7 @@ mi_decl_cache_align const mi_theap_t _mi_theap_empty_wrong = {
150
151
152
153
154
155
156
157
@@ -191,6 +193,7 @@ mi_decl_cache_align mi_theap_t theap_main = {
191
193
{ {0x846ca68b}, {0}, 0, true }, // random
192
194
195
196
197
198
199
0 commit comments