keep max 3 pages as retired
diff --git a/src/page.c b/src/page.c index 417e100..d315e85 100644 --- a/src/page.c +++ b/src/page.c
@@ -411,7 +411,8 @@ // _mi_arenas_collect(false, false, theap->tld); // allow purging } -#define MI_RETIRE_CYCLES (16) +#define MI_RETIRE_CYCLES (16) /* keep a retired page around for about 16 "cycles" before free'ing it */ +#define MI_RETIRE_MAX_PAGES (3) /* keep at most N pages per size bin as retired */ // Retire a page with no more used blocks // Important to not retire too quickly though as new @@ -438,7 +439,7 @@ #if MI_RETIRE_CYCLES > 0 const size_t bsize = mi_page_block_size(page); if mi_likely( /* bsize < MI_MAX_RETIRE_SIZE && */ !mi_page_queue_is_special(pq)) { // not full or huge queue? - if (pq->last==page && pq->first==page) { // the only page in the queue? + if (pq->count <= MI_RETIRE_MAX_PAGES) { // at most N pages left? // pq->last==page && pq->first==page) { // the only page in the queue? mi_theap_t* theap = mi_page_theap(page); mi_theap_stat_counter_increase(theap, pages_retire, 1); page->retire_expire = (bsize <= MI_SMALL_MAX_OBJ_SIZE ? MI_RETIRE_CYCLES : MI_RETIRE_CYCLES/4); @@ -477,29 +478,35 @@ } } +static void mi_page_try_retire(mi_page_queue_t* pq, mi_page_t* page, size_t bin, bool force, size_t* min, size_t* max) { + if (mi_page_all_free(page)) { + page->retire_expire--; + if (page->retire_expire == 0 || force) { + _mi_page_free(page, pq); + } + else { + // keep retired, update min/max + if (bin < *min) *min = bin; + if (bin > *max) *max = bin; + } + } + else { + page->retire_expire = 0; + } +} + // free retired pages: we don't need to look at the entire queues // since we only retire pages that are at the head position in a queue. void _mi_theap_collect_retired(mi_theap_t* theap, bool force) { size_t min = MI_BIN_FULL; size_t max = 0; for(size_t bin = theap->page_retired_min; bin <= theap->page_retired_max; bin++) { - mi_page_queue_t* pq = &theap->pages[bin]; - mi_page_t* page = pq->first; - if (page != NULL && page->retire_expire != 0) { - if (mi_page_all_free(page)) { - page->retire_expire--; - if (page->retire_expire == 0 || force) { - _mi_page_free(page, pq); - } - else { - // keep retired, update min/max - if (bin < min) min = bin; - if (bin > max) max = bin; - } - } - else { - page->retire_expire = 0; - } + mi_page_queue_t* pq = &theap->pages[bin]; + mi_page_t* page = pq->first; + for (int i = 0; i<MI_RETIRE_MAX_PAGES && page!=NULL && page->retire_expire==0; i++) { + mi_page_t* next = page-> next; + mi_page_try_retire(pq,page,bin,force,&min,&max); + page = next; } } theap->page_retired_min = min;