Extend the capacity (up to reserved) by initializing a free list We do at most `MI_MAX_EXTEND` to avoid touching too much memory Note: we also experimented with "bump" allocation on the first allocations but this did not speed up any benchmark (due to an extra test in malloc? or cache effects?)
| 596 | // allocations but this did not speed up any benchmark (due to an |
| 597 | // extra test in malloc? or cache effects?) |
| 598 | static void mi_page_extend_free(mi_heap_t* heap, mi_page_t* page, mi_tld_t* tld) { |
| 599 | MI_UNUSED(tld); |
| 600 | mi_assert_expensive(mi_page_is_valid_init(page)); |
| 601 | #if (MI_SECURE<=2) |
| 602 | mi_assert(page->free == NULL); |
| 603 | mi_assert(page->local_free == NULL); |
| 604 | if (page->free != NULL) return; |
| 605 | #endif |
| 606 | if (page->capacity >= page->reserved) return; |
| 607 | |
| 608 | size_t page_size; |
| 609 | _mi_page_start(_mi_page_segment(page), page, &page_size); |
| 610 | mi_stat_counter_increase(tld->stats.pages_extended, 1); |
| 611 | |
| 612 | // calculate the extend count |
| 613 | const size_t bsize = (page->xblock_size < MI_HUGE_BLOCK_SIZE ? page->xblock_size : page_size); |
| 614 | size_t extend = page->reserved - page->capacity; |
| 615 | mi_assert_internal(extend > 0); |
| 616 | |
| 617 | size_t max_extend = (bsize >= MI_MAX_EXTEND_SIZE ? MI_MIN_EXTEND : MI_MAX_EXTEND_SIZE/(uint32_t)bsize); |
| 618 | if (max_extend < MI_MIN_EXTEND) { max_extend = MI_MIN_EXTEND; } |
| 619 | mi_assert_internal(max_extend > 0); |
| 620 | |
| 621 | if (extend > max_extend) { |
| 622 | // ensure we don't touch memory beyond the page to reduce page commit. |
| 623 | // the `lean` benchmark tests this. Going from 1 to 8 increases rss by 50%. |
| 624 | extend = max_extend; |
| 625 | } |
| 626 | |
| 627 | mi_assert_internal(extend > 0 && extend + page->capacity <= page->reserved); |
| 628 | mi_assert_internal(extend < (1UL<<16)); |
| 629 | |
| 630 | // and append the extend the free list |
| 631 | if (extend < MI_MIN_SLICES || MI_SECURE==0) { //!mi_option_is_enabled(mi_option_secure)) { |
| 632 | mi_page_free_list_extend(page, bsize, extend, &tld->stats ); |
| 633 | } |
| 634 | else { |
| 635 | mi_page_free_list_extend_secure(heap, page, bsize, extend, &tld->stats); |
| 636 | } |
| 637 | // enable the new free list |
| 638 | page->capacity += (uint16_t)extend; |
| 639 | mi_stat_increase(tld->stats.page_committed, extend * bsize); |
| 640 | |
| 641 | // extension into zero initialized memory preserves the zero'd free list |
| 642 | if (!page->is_zero_init) { |
| 643 | page->is_zero = false; |
| 644 | } |
| 645 | mi_assert_expensive(mi_page_is_valid_init(page)); |
| 646 | } |
| 647 | |
| 648 | // Initialize a fresh page |
| 649 | static void mi_page_init(mi_heap_t* heap, mi_page_t* page, size_t block_size, mi_tld_t* tld) { |
no test coverage detected