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

[release/6.0] Cleaned up version of earlier PR #48601. #58544

Merged
merged 6 commits into from
Sep 2, 2021
Merged
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
90 changes: 79 additions & 11 deletions src/coreclr/gc/gc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2243,6 +2243,7 @@ double gc_heap::short_plugs_pad_ratio = 0;
#endif //SHORT_PLUGS

int gc_heap::generation_skip_ratio_threshold = 0;
int gc_heap::conserve_mem_setting = 0;

uint64_t gc_heap::suspended_start_time = 0;
uint64_t gc_heap::end_gc_time = 0;
Expand Down Expand Up @@ -12361,9 +12362,9 @@ void gc_heap::make_generation (int gen_num, heap_segment* seg, uint8_t* start)
#endif //DOUBLY_LINKED_FL

#ifdef FREE_USAGE_STATS
memset (gen->gen_free_spaces, 0, sizeof (gen.gen_free_spaces));
memset (gen->gen_current_pinned_free_spaces, 0, sizeof (gen.gen_current_pinned_free_spaces));
memset (gen->gen_plugs, 0, sizeof (gen.gen_plugs));
memset (gen->gen_free_spaces, 0, sizeof (gen->gen_free_spaces));
memset (gen->gen_current_pinned_free_spaces, 0, sizeof (gen->gen_current_pinned_free_spaces));
memset (gen->gen_plugs, 0, sizeof (gen->gen_plugs));
#endif //FREE_USAGE_STATS
}

Expand Down Expand Up @@ -12958,6 +12959,14 @@ gc_heap::init_semi_shared()
#endif //FEATURE_LOH_COMPACTION
#endif //FEATURE_EVENT_TRACE

conserve_mem_setting = (int)GCConfig::GetGCConserveMem();
if (conserve_mem_setting < 0)
conserve_mem_setting = 0;
if (conserve_mem_setting > 9)
conserve_mem_setting = 9;

dprintf (1, ("conserve_mem_setting = %d", conserve_mem_setting));

ret = 1;

cleanup:
Expand Down Expand Up @@ -17477,7 +17486,6 @@ void gc_heap::init_free_and_plug()
#else
memset (gen->gen_free_spaces, 0, sizeof (gen->gen_free_spaces));
#endif //DOUBLY_LINKED_FL
memset (gen->gen_plugs_allocated_in_free, 0, sizeof (gen->gen_plugs_allocated_in_free));
memset (gen->gen_plugs, 0, sizeof (gen->gen_plugs));
memset (gen->gen_current_pinned_free_spaces, 0, sizeof (gen->gen_current_pinned_free_spaces));
}
Expand All @@ -17495,7 +17503,7 @@ void gc_heap::init_free_and_plug()

void gc_heap::print_free_and_plug (const char* msg)
{
#if defined(FREE_USAGE_STATS) && defined(SIMPLE_DPRINTF)
#ifdef FREE_USAGE_STATS
int older_gen = ((settings.condemned_generation == max_generation) ? max_generation : (settings.condemned_generation + 1));
for (int i = 0; i <= older_gen; i++)
{
Expand All @@ -17516,7 +17524,7 @@ void gc_heap::print_free_and_plug (const char* msg)
}
#else
UNREFERENCED_PARAMETER(msg);
#endif //FREE_USAGE_STATS && SIMPLE_DPRINTF
#endif //FREE_USAGE_STATS
}

// replace with allocator::first_suitable_bucket
Expand Down Expand Up @@ -17588,8 +17596,8 @@ void gc_heap::add_gen_free (int gen_number, size_t free_size)
(gen->gen_free_spaces[i])++;
if (gen_number == max_generation)
{
dprintf (3, ("Mb b%d: f+ %Id (%Id->%Id)",
i, free_size, (gen->gen_free_spaces[i]).num_items, (gen->gen_free_spaces[i]).total_size));
dprintf (3, ("Mb b%d: f+ %Id (%Id)",
i, free_size, gen->gen_free_spaces[i]));
}
#else
UNREFERENCED_PARAMETER(gen_number);
Expand All @@ -17611,8 +17619,8 @@ void gc_heap::remove_gen_free (int gen_number, size_t free_size)
(gen->gen_free_spaces[i])--;
if (gen_number == max_generation)
{
dprintf (3, ("Mb b%d: f- %Id (%Id->%Id)",
i, free_size, (gen->gen_free_spaces[i]).num_items, (gen->gen_free_spaces[i]).total_size));
dprintf (3, ("Mb b%d: f- %Id (%Id)",
i, free_size, gen->gen_free_spaces[i]));
}
#else
UNREFERENCED_PARAMETER(gen_number);
Expand Down Expand Up @@ -18809,6 +18817,37 @@ int gc_heap::joined_generation_to_condemn (BOOL should_evaluate_elevation,
}
}

if ((conserve_mem_setting != 0) && (n == max_generation))
{
float frag_limit = 1.0f - conserve_mem_setting / 10.0f;

size_t loh_size = get_total_gen_size (loh_generation);
size_t gen2_size = get_total_gen_size (max_generation);
float loh_frag_ratio = 0.0f;
float combined_frag_ratio = 0.0f;
if (loh_size != 0)
{
size_t loh_frag = get_total_gen_fragmentation (loh_generation);
size_t gen2_frag = get_total_gen_fragmentation (max_generation);
loh_frag_ratio = (float)loh_frag / (float)loh_size;
combined_frag_ratio = (float)(gen2_frag + loh_frag) / (float)(gen2_size + loh_size);
}
if (combined_frag_ratio > frag_limit)
{
dprintf (GTC_LOG, ("combined frag: %f > limit %f, loh frag: %f", combined_frag_ratio, frag_limit, loh_frag_ratio));
gc_data_global.gen_to_condemn_reasons.set_condition (gen_max_high_frag_p);

n = max_generation;
*blocking_collection_p = TRUE;
if (loh_frag_ratio > frag_limit)
{
settings.loh_compaction = TRUE;

dprintf (GTC_LOG, ("compacting LOH due to GCConserveMem setting"));
}
}
}

#ifdef BGC_SERVO_TUNING
if (bgc_tuning::should_trigger_ngc2())
{
Expand Down Expand Up @@ -23967,6 +24006,21 @@ size_t gc_heap::get_total_gen_estimated_reclaim (int gen_number)
return total_estimated_reclaim;
}

size_t gc_heap::get_total_gen_size (int gen_number)
{
#ifdef MULTIPLE_HEAPS
size_t size = 0;
for (int hn = 0; hn < gc_heap::n_heaps; hn++)
{
gc_heap* hp = gc_heap::g_heaps[hn];
size += hp->generation_size (gen_number);
}
#else
size_t size = generation_size (gen_number);
#endif //MULTIPLE_HEAPS
return size;
}

size_t gc_heap::committed_size()
{
size_t total_committed = 0;
Expand Down Expand Up @@ -26128,7 +26182,7 @@ BOOL gc_heap::plan_loh()

void gc_heap::compact_loh()
{
assert (loh_compaction_requested() || heap_hard_limit);
assert (loh_compaction_requested() || heap_hard_limit || conserve_mem_setting);

#ifdef FEATURE_EVENT_TRACE
uint64_t start_time, end_time;
Expand Down Expand Up @@ -37909,6 +37963,19 @@ size_t gc_heap::desired_new_allocation (dynamic_data* dd,
cst = min (1.0f, float (out) / float (dd_begin_data_size (dd)));

f = surv_to_growth (cst, limit, max_limit);
if (conserve_mem_setting != 0)
{
// if this is set, compute a growth factor based on it.
// example: a setting of 6 means we have a goal of 60% live data
// this means we allow 40% fragmentation
// to keep heap size stable, we only use half of that (20%) for new allocation
// f is (live data + new allocation)/(live data), so would be (60% + 20%) / 60% or 1.33
float f_conserve = ((10.0f / conserve_mem_setting) - 1) * 0.5f + 1.0f;

// use the smaller one
f = min (f, f_conserve);
}

size_t max_growth_size = (size_t)(max_size / f);
if (current_size >= max_growth_size)
{
Expand All @@ -37932,6 +37999,7 @@ size_t gc_heap::desired_new_allocation (dynamic_data* dd,
#ifdef BGC_SERVO_TUNING
!bgc_tuning::fl_tuning_triggered &&
#endif //BGC_SERVO_TUNING
(conserve_mem_setting == 0) &&
(dd_fragmentation (dd) > ((size_t)((f-1)*current_size))))
{
//reducing allocation in case of fragmentation
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/gc/gcconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ class GCConfigStringHolder
INT_CONFIG (GCHeapHardLimitLOHPercent, "GCHeapHardLimitLOHPercent", "System.GC.HeapHardLimitLOHPercent", 0, "Specifies the GC heap LOH usage as a percentage of the total memory") \
INT_CONFIG (GCHeapHardLimitPOHPercent, "GCHeapHardLimitPOHPercent", "System.GC.HeapHardLimitPOHPercent", 0, "Specifies the GC heap POH usage as a percentage of the total memory") \
INT_CONFIG (GCEnabledInstructionSets, "GCEnabledInstructionSets", NULL, -1, "Specifies whether GC can use AVX2 or AVX512F - 0 for neither, 1 for AVX2, 3 for AVX512F")\
INT_CONFIG (GCConserveMem, "GCConserveMemory", NULL, 0, "Specifies how hard GC should try to conserve memory - values 0-9") \

// This class is responsible for retreiving configuration information
// for how the GC should operate.
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/gc/gcpriv.h
Original file line number Diff line number Diff line change
Expand Up @@ -3187,6 +3187,8 @@ class gc_heap
PER_HEAP_ISOLATED
size_t get_total_gen_estimated_reclaim (int gen_number);
PER_HEAP_ISOLATED
size_t get_total_gen_size (int gen_number);
PER_HEAP_ISOLATED
void get_memory_info (uint32_t* memory_load,
uint64_t* available_physical=NULL,
uint64_t* available_page_file=NULL);
Expand Down Expand Up @@ -4663,6 +4665,9 @@ class gc_heap
PER_HEAP_ISOLATED
int generation_skip_ratio_threshold;

PER_HEAP_ISOLATED
int conserve_mem_setting;

PER_HEAP
BOOL gen0_bricks_cleared;
PER_HEAP
Expand Down