Skip to content

Commit 9c7b5a8

Browse files
[release/7.0] Gradual decommit in wks (#76306)
* Initial version of gradual decommit for WKS. This is the regions version modeled after the behavior of the segments version. Idea is simply to limit the amount of decommitted memory based on the time since the last GC. * Change decommit_step to take a step_milliseconds parameter - this makes the logic for the WKS decommit more straightforward. * Only do decommits at most every 100 milliseconds to limit the number of decommitted regions. * Address code review feedback: disable the logic in decommit_ephemeral_segment_pages for WKS, some changes in distribute_free_regions as a consequence. * Remove unused static field ephemeral_elapsed. * Fix typo in comment. Co-authored-by: Peter Sollich <petersol@microsoft.com>
1 parent 10f8e71 commit 9c7b5a8

2 files changed

Lines changed: 29 additions & 8 deletions

File tree

src/coreclr/gc/gc.cpp

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6760,7 +6760,7 @@ void gc_heap::gc_thread_function ()
67606760
uint32_t wait_result = gc_heap::ee_suspend_event.Wait(gradual_decommit_in_progress_p ? DECOMMIT_TIME_STEP_MILLISECONDS : INFINITE, FALSE);
67616761
if (wait_result == WAIT_TIMEOUT)
67626762
{
6763-
gradual_decommit_in_progress_p = decommit_step ();
6763+
gradual_decommit_in_progress_p = decommit_step (DECOMMIT_TIME_STEP_MILLISECONDS);
67646764
continue;
67656765
}
67666766

@@ -6853,7 +6853,7 @@ void gc_heap::gc_thread_function ()
68536853
// check if we should do some decommitting
68546854
if (gradual_decommit_in_progress_p)
68556855
{
6856-
gradual_decommit_in_progress_p = decommit_step ();
6856+
gradual_decommit_in_progress_p = decommit_step (DECOMMIT_TIME_STEP_MILLISECONDS);
68576857
}
68586858
}
68596859
else
@@ -12601,7 +12601,7 @@ void gc_heap::distribute_free_regions()
1260112601
global_regions_to_decommit[kind].transfer_regions (&hp->free_regions[kind]);
1260212602
}
1260312603
}
12604-
while (decommit_step())
12604+
while (decommit_step(DECOMMIT_TIME_STEP_MILLISECONDS))
1260512605
{
1260612606
}
1260712607
#ifdef MULTIPLE_HEAPS
@@ -12853,8 +12853,29 @@ void gc_heap::distribute_free_regions()
1285312853
}
1285412854
}
1285512855
#else //MULTIPLE_HEAPS
12856-
while (decommit_step())
12856+
// we want to limit the amount of decommit we do per time to indirectly
12857+
// limit the amount of time spent in recommit and page faults
12858+
// we use the elapsed time since the last GC to arrive at the desired
12859+
// decommit size
12860+
// we limit the elapsed time to 10 seconds to avoid spending too much time decommitting
12861+
// if less than DECOMMIT_TIME_STEP_MILLISECONDS elapsed, we don't decommit -
12862+
// we don't want to decommit fractions of regions here
12863+
dynamic_data* dd0 = dynamic_data_of (0);
12864+
size_t ephemeral_elapsed = (size_t)((dd_time_clock (dd0) - gc_last_ephemeral_decommit_time) / 1000);
12865+
if (ephemeral_elapsed >= DECOMMIT_TIME_STEP_MILLISECONDS)
12866+
{
12867+
gc_last_ephemeral_decommit_time = dd_time_clock (dd0);
12868+
size_t decommit_step_milliseconds = min (ephemeral_elapsed, (10*1000));
12869+
12870+
decommit_step (decommit_step_milliseconds);
12871+
}
12872+
// transfer any remaining regions on the decommit list back to the free list
12873+
for (int kind = basic_free_region; kind < count_free_region_kinds; kind++)
1285712874
{
12875+
if (global_regions_to_decommit[kind].get_num_free_regions() != 0)
12876+
{
12877+
free_regions[kind].transfer_regions (&global_regions_to_decommit[kind]);
12878+
}
1285812879
}
1285912880
#endif //MULTIPLE_HEAPS
1286012881
#endif //USE_REGIONS
@@ -40567,7 +40588,7 @@ void gc_heap::decommit_ephemeral_segment_pages()
4056740588
(heap_segment_committed (tail_region) - heap_segment_mem (tail_region))/1024,
4056840589
(decommit_target - heap_segment_mem (tail_region))/1024));
4056940590
}
40570-
#else //MULTIPLE_HEAPS && USE_REGIONS
40591+
#elif !defined(USE_REGIONS)
4057140592

4057240593
dynamic_data* dd0 = dynamic_data_of (0);
4057340594

@@ -40634,12 +40655,12 @@ void gc_heap::decommit_ephemeral_segment_pages()
4063440655
}
4063540656

4063640657
// return true if we actually decommitted anything
40637-
bool gc_heap::decommit_step ()
40658+
bool gc_heap::decommit_step (uint64_t step_milliseconds)
4063840659
{
4063940660
size_t decommit_size = 0;
4064040661

4064140662
#ifdef USE_REGIONS
40642-
const size_t max_decommit_step_size = DECOMMIT_SIZE_PER_MILLISECOND * DECOMMIT_TIME_STEP_MILLISECONDS;
40663+
const size_t max_decommit_step_size = DECOMMIT_SIZE_PER_MILLISECOND * step_milliseconds;
4064340664
for (int kind = basic_free_region; kind < count_free_region_kinds; kind++)
4064440665
{
4064540666
dprintf (REGIONS_LOG, ("decommit_step %d, regions_to_decommit = %Id",

src/coreclr/gc/gcpriv.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2065,7 +2065,7 @@ class gc_heap
20652065
PER_HEAP
20662066
size_t decommit_heap_segment_pages_worker (heap_segment* seg, uint8_t *new_committed);
20672067
PER_HEAP_ISOLATED
2068-
bool decommit_step ();
2068+
bool decommit_step (uint64_t step_milliseconds);
20692069
PER_HEAP
20702070
void decommit_heap_segment (heap_segment* seg);
20712071
PER_HEAP_ISOLATED

0 commit comments

Comments
 (0)