mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-04 22:49:32 +03:00
add option to reset eagerly when a segment is abandoned
This commit is contained in:
parent
b8072aaacb
commit
8d8f355ed0
3 changed files with 14 additions and 7 deletions
|
@ -273,6 +273,7 @@ typedef enum mi_option_e {
|
||||||
mi_option_reserve_huge_os_pages,
|
mi_option_reserve_huge_os_pages,
|
||||||
mi_option_segment_cache,
|
mi_option_segment_cache,
|
||||||
mi_option_page_reset,
|
mi_option_page_reset,
|
||||||
|
mi_option_abandoned_page_reset,
|
||||||
mi_option_segment_reset,
|
mi_option_segment_reset,
|
||||||
mi_option_eager_commit_delay,
|
mi_option_eager_commit_delay,
|
||||||
mi_option_reset_delay,
|
mi_option_reset_delay,
|
||||||
|
|
|
@ -68,6 +68,7 @@ static mi_option_desc_t options[_mi_option_last] =
|
||||||
{ 0, UNINIT, MI_OPTION(reserve_huge_os_pages) },
|
{ 0, UNINIT, MI_OPTION(reserve_huge_os_pages) },
|
||||||
{ 0, UNINIT, MI_OPTION(segment_cache) }, // cache N segments per thread
|
{ 0, UNINIT, MI_OPTION(segment_cache) }, // cache N segments per thread
|
||||||
{ 0, UNINIT, MI_OPTION(page_reset) }, // reset page memory on free
|
{ 0, UNINIT, MI_OPTION(page_reset) }, // reset page memory on free
|
||||||
|
{ 0, UNINIT, MI_OPTION(abandoned_page_reset) },// reset free page memory when a thread terminates
|
||||||
{ 0, UNINIT, MI_OPTION(segment_reset) }, // reset segment memory on free (needs eager commit)
|
{ 0, UNINIT, MI_OPTION(segment_reset) }, // reset segment memory on free (needs eager commit)
|
||||||
{ 0, UNINIT, MI_OPTION(eager_commit_delay) }, // the first N segments per thread are not eagerly committed
|
{ 0, UNINIT, MI_OPTION(eager_commit_delay) }, // the first N segments per thread are not eagerly committed
|
||||||
{ 100, UNINIT, MI_OPTION(reset_delay) }, // reset delay in milli-seconds
|
{ 100, UNINIT, MI_OPTION(reset_delay) }, // reset delay in milli-seconds
|
||||||
|
|
|
@ -326,12 +326,15 @@ static void mi_pages_reset_remove(mi_page_t* page, mi_segments_tld_t* tld) {
|
||||||
page->used = 0;
|
page->used = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mi_pages_reset_remove_all_in_segment(mi_segment_t* segment, mi_segments_tld_t* tld) {
|
static void mi_pages_reset_remove_all_in_segment(mi_segment_t* segment, bool force_reset, mi_segments_tld_t* tld) {
|
||||||
if (segment->mem_is_fixed) return;
|
if (segment->mem_is_fixed) return; // never reset in huge OS pages
|
||||||
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->segment_in_use && !page->is_reset) {
|
if (!page->segment_in_use && !page->is_reset) {
|
||||||
mi_pages_reset_remove(page, tld);
|
mi_pages_reset_remove(page, tld);
|
||||||
|
if (force_reset) {
|
||||||
|
mi_page_reset(segment, page, 0, tld);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mi_assert_internal(mi_page_not_in_queue(page,tld));
|
mi_assert_internal(mi_page_not_in_queue(page,tld));
|
||||||
|
@ -668,9 +671,11 @@ static mi_segment_t* mi_segment_alloc(size_t required, mi_page_kind_t page_kind,
|
||||||
|
|
||||||
|
|
||||||
static void mi_segment_free(mi_segment_t* segment, bool force, mi_segments_tld_t* tld) {
|
static void mi_segment_free(mi_segment_t* segment, bool force, mi_segments_tld_t* tld) {
|
||||||
UNUSED(force);
|
UNUSED(force);
|
||||||
mi_assert(segment != NULL);
|
mi_assert(segment != NULL);
|
||||||
mi_pages_reset_remove_all_in_segment(segment, tld);
|
// note: don't reset pages even on abandon as the whole segment is freed? (and ready for reuse)
|
||||||
|
bool force_reset = (force && mi_option_is_enabled(mi_option_abandoned_page_reset));
|
||||||
|
mi_pages_reset_remove_all_in_segment(segment, force_reset, tld);
|
||||||
mi_segment_remove_from_free_queue(segment,tld);
|
mi_segment_remove_from_free_queue(segment,tld);
|
||||||
|
|
||||||
mi_assert_expensive(!mi_segment_queue_contains(&tld->small_free, segment));
|
mi_assert_expensive(!mi_segment_queue_contains(&tld->small_free, segment));
|
||||||
|
@ -840,8 +845,8 @@ static void mi_segment_abandon(mi_segment_t* segment, mi_segments_tld_t* tld) {
|
||||||
mi_assert_expensive(mi_segment_is_valid(segment,tld));
|
mi_assert_expensive(mi_segment_is_valid(segment,tld));
|
||||||
|
|
||||||
// remove the segment from the free page queue if needed
|
// remove the segment from the free page queue if needed
|
||||||
mi_reset_delayed(tld);
|
mi_reset_delayed(tld);
|
||||||
mi_pages_reset_remove_all_in_segment(segment, tld); // do not force reset on free pages in an abandoned segment, as it is already done in segment_thread_collect
|
mi_pages_reset_remove_all_in_segment(segment, mi_option_is_enabled(mi_option_abandoned_page_reset), tld);
|
||||||
mi_segment_remove_from_free_queue(segment, tld);
|
mi_segment_remove_from_free_queue(segment, tld);
|
||||||
mi_assert_internal(segment->next == NULL && segment->prev == NULL);
|
mi_assert_internal(segment->next == NULL && segment->prev == NULL);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue