Skip to content
31 changes: 24 additions & 7 deletions src/coreclr/gc/gc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2247,6 +2247,8 @@ gc_history_global gc_heap::gc_data_global;

uint64_t gc_heap::gc_last_ephemeral_decommit_time = 0;

size_t gc_heap::ephemeral_elapsed = 0;

CLRCriticalSection gc_heap::check_commit_cs;

size_t gc_heap::current_total_committed = 0;
Expand Down Expand Up @@ -6752,7 +6754,7 @@ void gc_heap::gc_thread_function ()
uint32_t wait_result = gc_heap::ee_suspend_event.Wait(gradual_decommit_in_progress_p ? DECOMMIT_TIME_STEP_MILLISECONDS : INFINITE, FALSE);
if (wait_result == WAIT_TIMEOUT)
{
gradual_decommit_in_progress_p = decommit_step ();
gradual_decommit_in_progress_p = decommit_step (DECOMMIT_TIME_STEP_MILLISECONDS);
continue;
}

Expand Down Expand Up @@ -6845,7 +6847,7 @@ void gc_heap::gc_thread_function ()
// check if we should do some decommitting
if (gradual_decommit_in_progress_p)
{
gradual_decommit_in_progress_p = decommit_step ();
gradual_decommit_in_progress_p = decommit_step (DECOMMIT_TIME_STEP_MILLISECONDS);
}
}
else
Expand Down Expand Up @@ -12593,7 +12595,7 @@ void gc_heap::distribute_free_regions()
global_regions_to_decommit[kind].transfer_regions (&hp->free_regions[kind]);
}
}
while (decommit_step())
while (decommit_step(DECOMMIT_TIME_STEP_MILLISECONDS))
{
}
#ifdef MULTIPLE_HEAPS
Expand Down Expand Up @@ -12845,8 +12847,23 @@ void gc_heap::distribute_free_regions()
}
}
#else //MULTIPLE_HEAPS
while (decommit_step())
// we want to limit the amount of decommit we do per time to indirectly
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is similar logic already implemented for the svr case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, in SVR case gc thread #0 wakes up every 100 ms and call decommit_step().

// limit the amount of time spent in recommit and page faults
// we use the elapsed time since the last GC to arrive at the desired
// decommit size
// we limit the elapsed time to 10 seconds to avoid spending too much time decommitting
size_t decommit_step_milliseconds = min (ephemeral_elapsed, (10*1000));

decommit_step (decommit_step_milliseconds);

// transfer any remaining regions on the decommit list back to the free list
for (int kind = basic_free_region; kind < count_free_region_kinds; kind++)
{
if (global_regions_to_decommit[kind].get_num_free_regions() != 0)
{
gc_heap* hp = pGenGCHeap;
hp->free_regions[kind].transfer_regions (&global_regions_to_decommit[kind]);
}
}
#endif //MULTIPLE_HEAPS
#endif //USE_REGIONS
Expand Down Expand Up @@ -40399,7 +40416,7 @@ void gc_heap::decommit_ephemeral_segment_pages()
#ifndef MULTIPLE_HEAPS
// we want to limit the amount of decommit we do per time to indirectly
// limit the amount of time spent in recommit and page faults
size_t ephemeral_elapsed = (size_t)((dd_time_clock (dd0) - gc_last_ephemeral_decommit_time) / 1000);
ephemeral_elapsed = (size_t)((dd_time_clock (dd0) - gc_last_ephemeral_decommit_time) / 1000);
gc_last_ephemeral_decommit_time = dd_time_clock (dd0);

// this is the amount we were planning to decommit
Expand All @@ -40420,12 +40437,12 @@ void gc_heap::decommit_ephemeral_segment_pages()
}

// return true if we actually decommitted anything
bool gc_heap::decommit_step ()
bool gc_heap::decommit_step (uint64_t step_milliseconds)
{
size_t decommit_size = 0;

#ifdef USE_REGIONS
const size_t max_decommit_step_size = DECOMMIT_SIZE_PER_MILLISECOND * DECOMMIT_TIME_STEP_MILLISECONDS;
const size_t max_decommit_step_size = DECOMMIT_SIZE_PER_MILLISECOND * step_milliseconds;
for (int kind = basic_free_region; kind < count_free_region_kinds; kind++)
{
dprintf (REGIONS_LOG, ("decommit_step %d, regions_to_decommit = %Id",
Expand Down
5 changes: 4 additions & 1 deletion src/coreclr/gc/gcpriv.h
Original file line number Diff line number Diff line change
Expand Up @@ -2046,7 +2046,7 @@ class gc_heap
PER_HEAP
size_t decommit_heap_segment_pages_worker (heap_segment* seg, uint8_t *new_committed);
PER_HEAP_ISOLATED
bool decommit_step ();
bool decommit_step (uint64_t step_milliseconds);
PER_HEAP
void decommit_heap_segment (heap_segment* seg);
PER_HEAP_ISOLATED
Expand Down Expand Up @@ -3916,6 +3916,9 @@ class gc_heap
PER_HEAP_ISOLATED
uint64_t gc_last_ephemeral_decommit_time;

PER_HEAP_ISOLATED
size_t ephemeral_elapsed;

#ifdef SHORT_PLUGS
PER_HEAP_ISOLATED
double short_plugs_pad_ratio;
Expand Down