more precise memory reset

This commit is contained in:
daan 2019-11-24 14:40:47 -08:00
parent 4a0d35afd0
commit 727d33b96f
2 changed files with 31 additions and 35 deletions

View file

@ -306,12 +306,15 @@ static void* mi_region_try_alloc(size_t blocks, bool* commit, bool* is_large, bo
// unreset reset blocks // unreset reset blocks
if (mi_bitmap_is_any_claimed(&region->reset, 1, blocks, bit_idx)) { if (mi_bitmap_is_any_claimed(&region->reset, 1, blocks, bit_idx)) {
// some blocks are still reset
mi_assert_internal(!info.is_large); mi_assert_internal(!info.is_large);
mi_assert_internal(!mi_option_is_enabled(mi_option_eager_commit) || *commit); mi_assert_internal(!mi_option_is_enabled(mi_option_eager_commit) || *commit);
mi_bitmap_unclaim(&region->reset, 1, blocks, bit_idx); mi_bitmap_unclaim(&region->reset, 1, blocks, bit_idx);
bool reset_zero = false; if (*commit || !mi_option_is_enabled(mi_option_reset_decommits)) { // only if needed
_mi_mem_unreset(p, blocks * MI_SEGMENT_SIZE, &reset_zero, tld); bool reset_zero = false;
if (reset_zero) *is_zero = true; _mi_mem_unreset(p, blocks * MI_SEGMENT_SIZE, &reset_zero, tld);
if (reset_zero) *is_zero = true;
}
} }
mi_assert_internal(!mi_bitmap_is_any_claimed(&region->reset, 1, blocks, bit_idx)); mi_assert_internal(!mi_bitmap_is_any_claimed(&region->reset, 1, blocks, bit_idx));
@ -409,8 +412,9 @@ void _mi_mem_free(void* p, size_t size, size_t id, bool full_commit, bool any_re
} }
// reset the blocks to reduce the working set. // reset the blocks to reduce the working set.
if (!info.is_large && mi_option_is_enabled(mi_option_segment_reset) && if (!info.is_large && mi_option_is_enabled(mi_option_segment_reset)
mi_option_is_enabled(mi_option_eager_commit)) // cannot reset halfway committed segments, use only `option_page_reset` instead && (mi_option_is_enabled(mi_option_eager_commit) ||
mi_option_is_enabled(mi_option_reset_decommits))) // cannot reset halfway committed segments, use only `option_page_reset` instead
{ {
bool any_unreset; bool any_unreset;
mi_bitmap_claim(&region->reset, 1, blocks, bit_idx, &any_unreset); mi_bitmap_claim(&region->reset, 1, blocks, bit_idx, &any_unreset);

View file

@ -320,10 +320,10 @@ static void mi_segment_os_free(mi_segment_t* segment, size_t segment_size, mi_se
bool any_reset = false; bool any_reset = false;
for (size_t i = 0; i < segment->capacity; i++) { for (size_t i = 0; i < segment->capacity; i++) {
mi_page_t* page = &segment->pages[i]; mi_page_t* page = &segment->pages[i];
if (!page->is_committed) fully_committed = false; if (!page->is_committed) { fully_committed = false; }
else if (page->is_reset) { if (page->is_reset) {
any_reset = true; any_reset = true;
// mi_page_unreset(segment, page, 0, tld); if (mi_option_is_enabled(mi_option_reset_decommits)) { fully_committed = false;}
} }
} }
_mi_mem_free(segment, segment_size, segment->memid, fully_committed, any_reset, tld->os); _mi_mem_free(segment, segment_size, segment->memid, fully_committed, any_reset, tld->os);
@ -419,7 +419,7 @@ static mi_segment_t* mi_segment_alloc(size_t required, mi_page_kind_t page_kind,
// Initialize parameters // Initialize parameters
bool eager_delayed = (page_kind <= MI_PAGE_MEDIUM && tld->count < (size_t)mi_option_get(mi_option_eager_commit_delay)); bool eager_delayed = (page_kind <= MI_PAGE_MEDIUM && tld->count < (size_t)mi_option_get(mi_option_eager_commit_delay));
bool eager = !eager_delayed && mi_option_is_enabled(mi_option_eager_commit); bool eager = !eager_delayed && mi_option_is_enabled(mi_option_eager_commit);
bool commit = eager || (page_kind >= MI_PAGE_LARGE); bool commit = eager; // || (page_kind >= MI_PAGE_LARGE);
bool pages_still_good = false; bool pages_still_good = false;
bool is_zero = false; bool is_zero = false;
@ -431,18 +431,23 @@ static mi_segment_t* mi_segment_alloc(size_t required, mi_page_kind_t page_kind,
} }
else else
{ {
if (MI_SECURE!=0) {
mi_assert_internal(!segment->mem_is_fixed);
mi_segment_protect(segment, false); // reset protection if the page kind differs
}
// different page kinds; unreset any reset pages, and unprotect // different page kinds; unreset any reset pages, and unprotect
// TODO: optimize cache pop to return fitting pages if possible? // TODO: optimize cache pop to return fitting pages if possible?
for (size_t i = 0; i < segment->capacity; i++) { for (size_t i = 0; i < segment->capacity; i++) {
mi_page_t* page = &segment->pages[i]; mi_page_t* page = &segment->pages[i];
if (page->is_reset) { if (page->is_reset) {
mi_page_unreset(segment, page, 0, tld); // todo: only unreset the part that was reset? (instead of the full page) if (!commit && mi_option_is_enabled(mi_option_reset_decommits)) {
page->is_reset = false;
}
else {
mi_page_unreset(segment, page, 0, tld); // todo: only unreset the part that was reset? (instead of the full page)
}
} }
} }
if (MI_SECURE!=0) {
mi_assert_internal(!segment->mem_is_fixed);
mi_segment_protect(segment, false); // reset protection if the page kind differs
}
} }
} }
else { else {
@ -491,7 +496,7 @@ static mi_segment_t* mi_segment_alloc(size_t required, mi_page_kind_t page_kind,
segment->segment_info_size = pre_size; segment->segment_info_size = pre_size;
segment->thread_id = _mi_thread_id(); segment->thread_id = _mi_thread_id();
segment->cookie = _mi_ptr_cookie(segment); segment->cookie = _mi_ptr_cookie(segment);
_mi_stat_increase(&tld->stats->page_committed, segment->segment_info_size); // _mi_stat_increase(&tld->stats->page_committed, segment->segment_info_size);
// set protection // set protection
mi_segment_protect(segment, true); mi_segment_protect(segment, true);
@ -513,17 +518,6 @@ static void mi_segment_free(mi_segment_t* segment, bool force, mi_segments_tld_t
mi_assert(segment->prev == NULL); mi_assert(segment->prev == NULL);
_mi_stat_decrease(&tld->stats->page_committed, segment->segment_info_size); _mi_stat_decrease(&tld->stats->page_committed, segment->segment_info_size);
// update reset memory statistics
/*
for (uint8_t i = 0; i < segment->capacity; i++) {
mi_page_t* page = &segment->pages[i];
if (page->is_reset) {
page->is_reset = false;
mi_stat_decrease( tld->stats->reset,mi_page_size(page));
}
}
*/
if (!force && mi_segment_cache_push(segment, tld)) { if (!force && mi_segment_cache_push(segment, tld)) {
// it is put in our cache // it is put in our cache
} }
@ -602,7 +596,7 @@ static void mi_segment_page_clear(mi_segment_t* segment, mi_page_t* page, mi_seg
// reset the page memory to reduce memory pressure? // reset the page memory to reduce memory pressure?
// note: must come after setting `segment_in_use` to false // note: must come after setting `segment_in_use` to false
mi_page_reset(segment, page, used_size, tld); mi_page_reset(segment, page, 0 /*used_size*/, tld);
} }
void _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld) void _mi_segment_page_free(mi_page_t* page, bool force, mi_segments_tld_t* tld)
@ -792,9 +786,8 @@ static mi_page_t* mi_segment_medium_page_alloc(mi_segments_tld_t* tld, mi_os_tld
static mi_page_t* mi_segment_large_page_alloc(mi_segments_tld_t* tld, mi_os_tld_t* os_tld) { static mi_page_t* mi_segment_large_page_alloc(mi_segments_tld_t* tld, mi_os_tld_t* os_tld) {
mi_segment_t* segment = mi_segment_alloc(0,MI_PAGE_LARGE,MI_LARGE_PAGE_SHIFT,tld,os_tld); mi_segment_t* segment = mi_segment_alloc(0,MI_PAGE_LARGE,MI_LARGE_PAGE_SHIFT,tld,os_tld);
if (segment == NULL) return NULL; if (segment == NULL) return NULL;
segment->used = 1; mi_page_t* page = mi_segment_find_free(segment, tld);
mi_page_t* page = &segment->pages[0]; mi_assert_internal(page != NULL);
page->segment_in_use = true;
#if MI_DEBUG>=2 #if MI_DEBUG>=2
_mi_segment_page_start(segment, page, sizeof(void*), NULL, NULL)[0] = 0; _mi_segment_page_start(segment, page, sizeof(void*), NULL, NULL)[0] = 0;
#endif #endif
@ -806,10 +799,9 @@ static mi_page_t* mi_segment_huge_page_alloc(size_t size, mi_segments_tld_t* tld
mi_segment_t* segment = mi_segment_alloc(size, MI_PAGE_HUGE, MI_SEGMENT_SHIFT,tld,os_tld); mi_segment_t* segment = mi_segment_alloc(size, MI_PAGE_HUGE, MI_SEGMENT_SHIFT,tld,os_tld);
if (segment == NULL) return NULL; if (segment == NULL) return NULL;
mi_assert_internal(mi_segment_page_size(segment) - segment->segment_info_size - (2*(MI_SECURE == 0 ? 0 : _mi_os_page_size())) >= size); mi_assert_internal(mi_segment_page_size(segment) - segment->segment_info_size - (2*(MI_SECURE == 0 ? 0 : _mi_os_page_size())) >= size);
segment->used = 1;
segment->thread_id = 0; // huge pages are immediately abandoned segment->thread_id = 0; // huge pages are immediately abandoned
mi_page_t* page = &segment->pages[0]; mi_page_t* page = mi_segment_find_free(segment, tld);
page->segment_in_use = true; mi_assert_internal(page != NULL);
return page; return page;
} }