Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce number of gen 2 GC under high memory load #83328

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 54 additions & 5 deletions src/coreclr/gc/gc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2374,6 +2374,8 @@ gc_latency_level gc_heap::latency_level = latency_level_default;

gc_mechanisms gc_heap::settings;

BOOL gc_heap::high_memory_compact_gtc_p;

gc_history_global gc_heap::gc_data_global;

uint64_t gc_heap::gc_last_ephemeral_decommit_time = 0;
Expand Down Expand Up @@ -2924,6 +2926,7 @@ BOOL gc_heap::heap_analyze_enabled = FALSE;

#ifndef MULTIPLE_HEAPS

bool gc_heap::maxgen_size_inc_per_heap_p = false;
alloc_list gc_heap::loh_alloc_list [NUM_LOH_ALIST-1];
alloc_list gc_heap::gen2_alloc_list[NUM_GEN2_ALIST-1];
alloc_list gc_heap::poh_alloc_list [NUM_POH_ALIST-1];
Expand Down Expand Up @@ -14754,6 +14757,8 @@ gc_heap::init_gc_heap (int h_number)

gen0_allocated_after_gc_p = false;

maxgen_size_inc_per_heap_p = false;

#ifdef RECORD_LOH_STATE
loh_state_index = 0;
#endif //RECORD_LOH_STATE
Expand Down Expand Up @@ -21442,19 +21447,29 @@ int gc_heap::generation_to_condemn (int n_initial,

high_memory_load = TRUE;

BOOL check_fragmentation = TRUE;
if (conserve_mem_setting != 0)
{
// optimization for high memory situations: check fragmentation only if
// we are about to do a gen 2 collection anyway or gen 2 grew in the last gen 1.
dynamic_data* dd_max = dynamic_data_of (max_generation);
bool would_trigger_gen2_p = (n == max_generation) || (((float)dd_new_allocation (dd_max) / (float)dd_desired_allocation (dd_max)) < 0.9);
check_fragmentation = (would_trigger_gen2_p || maxgen_size_inc_per_heap_p);
}

if (memory_load >= v_high_memory_load_th || low_memory_detected)
{
// TODO: Perhaps in 64-bit we should be estimating gen1's fragmentation as well since
// gen1/gen0 may take a lot more memory than gen2.
if (!high_fragmentation)
if (!high_fragmentation && check_fragmentation)
{
high_fragmentation = dt_estimate_reclaim_space_p (tuning_deciding_condemned_gen, max_generation);
}
v_high_memory_load = TRUE;
}
else
{
if (!high_fragmentation)
if (!high_fragmentation && check_fragmentation)
{
high_fragmentation = dt_estimate_high_frag_p (tuning_deciding_condemned_gen, max_generation, available_physical);
}
Expand Down Expand Up @@ -23732,6 +23747,10 @@ void gc_heap::garbage_collect (int n)
STRESS_HEAP_ARG(n)
);

// we have decided to do a blocking gen 2 collection due to high memory
// set flag so that decide_on_compacting can do the right thing
high_memory_compact_gtc_p = (settings.condemned_generation == max_generation) && should_do_blocking_collection;

STRESS_LOG1(LF_GCROOTS|LF_GC|LF_GCALLOC, LL_INFO10,
"condemned generation num: %d\n", settings.condemned_generation);

Expand Down Expand Up @@ -28739,6 +28758,9 @@ void gc_heap::mark_phase (int condemned_gen_number, BOOL mark_only_p)
static BOOL do_mark_steal_p = FALSE;
#endif //MH_SC_MARK

if (condemned_gen_number >= (max_generation - 1))
maxgen_size_inc_per_heap_p = false;

#ifdef FEATURE_CARD_MARKING_STEALING
reset_card_marking_enumerators();
#endif // FEATURE_CARD_MARKING_STEALING
Expand Down Expand Up @@ -32691,7 +32713,7 @@ void gc_heap::plan_phase (int condemned_gen_number)
dprintf (1, ("gen2 grew %zd (end seg alloc: %zd, condemned alloc: %zd",
growth, end_seg_allocated, condemned_allocated));

maxgen_size_inc_p = true;
maxgen_size_inc_per_heap_p = true;
}
else
{
Expand Down Expand Up @@ -32841,6 +32863,19 @@ void gc_heap::plan_phase (int condemned_gen_number)
}
}
#endif //!USE_REGIONS
// count number of heaps seeing gen 2 growth
int maxgen_size_inc_count = 0;
for (int i = 0; i < n_heaps; i++)
{
if (g_heaps[i]->maxgen_size_inc_per_heap_p)
{
maxgen_size_inc_count += 1;
}
}
// if it's the majority, set the global flag
if (maxgen_size_inc_count > (n_heaps / 2))
maxgen_size_inc_p = true;

if (maxgen_size_inc_p && provisional_mode_triggered
#ifdef BACKGROUND_GC
&& !is_bgc_in_progress()
Expand Down Expand Up @@ -32982,6 +33017,9 @@ void gc_heap::plan_phase (int condemned_gen_number)
rearrange_uoh_segments ();
}
#endif //!USE_REGIONS

maxgen_size_inc_p = maxgen_size_inc_per_heap_p;

if (maxgen_size_inc_p && provisional_mode_triggered
#ifdef BACKGROUND_GC
&& !is_bgc_in_progress()
Expand Down Expand Up @@ -44107,6 +44145,13 @@ BOOL gc_heap::decide_on_compacting (int condemned_gen_number,
#endif // BACKGROUND_GC
}

// if generation_to_condemn decided to do a full blocking GC,
// make sure to compact
if (high_memory_compact_gtc_p)
{
should_compact = TRUE;
}

#ifdef HOST_64BIT
// check for high memory situation
if(!should_compact)
Expand All @@ -44116,8 +44161,7 @@ BOOL gc_heap::decide_on_compacting (int condemned_gen_number,
num_heaps = gc_heap::n_heaps;
#endif // MULTIPLE_HEAPS

ptrdiff_t reclaim_space = generation_size(max_generation) - generation_plan_size(max_generation);

ptrdiff_t reclaim_space = fragmentation;
if((settings.entry_memory_load >= high_memory_load_th) && (settings.entry_memory_load < v_high_memory_load_th))
{
if(reclaim_space > (int64_t)(min_high_fragmentation_threshold (entry_available_physical_mem, num_heaps)))
Expand Down Expand Up @@ -45663,6 +45707,11 @@ void gc_heap::background_sweep()
current_sweep_seg = 0;
#endif //DOUBLY_LINKED_FL

// we just finished sweeping and thus created more space in gen 2
// so turn off this flag which may have been turned on by a gen 1
// collection that occurred before or during this background GC
maxgen_size_inc_per_heap_p = false;

enable_preemptive ();

#ifdef MULTIPLE_HEAPS
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/gc/gcpriv.h
Original file line number Diff line number Diff line change
Expand Up @@ -3430,6 +3430,8 @@ class gc_heap
PER_HEAP_FIELD_SINGLE_GC bool no_gc_oom_p;
PER_HEAP_FIELD_SINGLE_GC heap_segment* saved_loh_segment_no_gc;

PER_HEAP_FIELD_SINGLE_GC bool maxgen_size_inc_per_heap_p;

#ifdef MULTIPLE_HEAPS
#ifdef USE_REGIONS
PER_HEAP_FIELD_SINGLE_GC min_fl_list_info* min_fl_list;
Expand Down Expand Up @@ -4057,6 +4059,8 @@ class gc_heap

PER_HEAP_ISOLATED_FIELD_SINGLE_GC gc_mechanisms settings;

PER_HEAP_ISOLATED_FIELD_SINGLE_GC BOOL high_memory_compact_gtc_p;

#ifdef MULTIPLE_HEAPS
// These 2 fields' values do not change but are set/unset per GC
PER_HEAP_ISOLATED_FIELD_SINGLE_GC GCEvent gc_start_event;
Expand Down