Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
103 changes: 74 additions & 29 deletions src/coreclr/gc/gc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44216,38 +44216,42 @@ void gc_heap::init_static_data()
{
size_t gen0_min_size = get_gen0_min_size();

size_t gen0_max_size =
#ifdef MULTIPLE_HEAPS
max ((size_t)6*1024*1024, min ( Align(soh_segment_size/2), (size_t)200*1024*1024));
#else //MULTIPLE_HEAPS
(
#ifdef BACKGROUND_GC
gc_can_use_concurrent ?
6*1024*1024 :
#endif //BACKGROUND_GC
max ((size_t)6*1024*1024, min ( Align(soh_segment_size/2), (size_t)200*1024*1024))
);
#endif //MULTIPLE_HEAPS

gen0_max_size = max (gen0_min_size, gen0_max_size);

if (heap_hard_limit)
{
size_t gen0_max_size_seg = soh_segment_size / 4;
dprintf (GTC_LOG, ("limit gen0 max %zd->%zd", gen0_max_size, gen0_max_size_seg));
gen0_max_size = min (gen0_max_size, gen0_max_size_seg);
}
size_t gen0_max_size = 0;

size_t gen0_max_size_config = (size_t)GCConfig::GetGCGen0MaxBudget();

if (gen0_max_size_config)
{
gen0_max_size = min (gen0_max_size, gen0_max_size_config);
gen0_max_size = gen0_max_size_config;

#ifdef FEATURE_EVENT_TRACE
gen0_max_budget_from_config = gen0_max_size;
#endif //FEATURE_EVENT_TRACE
}
else
{
gen0_max_size =
#ifdef MULTIPLE_HEAPS
max ((size_t)6 * 1024 * 1024, min (Align(soh_segment_size / 2), (size_t)200 * 1024 * 1024));
#else //MULTIPLE_HEAPS
(
#ifdef BACKGROUND_GC
gc_can_use_concurrent ?
6 * 1024 * 1024 :
#endif //BACKGROUND_GC
max ((size_t)6 * 1024 * 1024, min (Align(soh_segment_size / 2), (size_t)200 * 1024 * 1024))
);
#endif //MULTIPLE_HEAPS

gen0_max_size = max (gen0_min_size, gen0_max_size);

if (heap_hard_limit)
{
size_t gen0_max_size_seg = soh_segment_size / 4;
dprintf (GTC_LOG, ("limit gen0 max %zd->%zd", gen0_max_size, gen0_max_size_seg));
gen0_max_size = min (gen0_max_size, gen0_max_size_seg);
}
}

gen0_max_size = Align (gen0_max_size);
gen0_min_size = min (gen0_min_size, gen0_max_size);
Expand Down Expand Up @@ -44284,6 +44288,17 @@ void gc_heap::init_static_data()
static_data_table[i][0].max_size = gen0_max_size;
static_data_table[i][1].max_size = gen1_max_size;
}

#ifdef DYNAMIC_HEAP_COUNT
if (gc_heap::dynamic_adaptation_mode == dynamic_adaptation_to_application_sizes)
{
gc_heap::dynamic_heap_count_data.min_gen0_new_allocation = gen0_min_size;
if (gen0_max_size_config)
{
gc_heap::dynamic_heap_count_data.max_gen0_new_allocation = gen0_max_size;
}
}
#endif //DYNAMIC_HEAP_COUNT
}

bool gc_heap::init_dynamic_data()
Expand Down Expand Up @@ -49735,13 +49750,43 @@ HRESULT GCHeap::Initialize()
}
// This should be adjusted based on the target tcp. See comments in gcpriv.h
gc_heap::dynamic_heap_count_data.around_target_threshold = 10.0;
// This should really be set as part of computing static data and should take conserve_mem_setting into consideration.
gc_heap::dynamic_heap_count_data.max_gen0_new_allocation = Align (min (dd_max_size (gc_heap::g_heaps[0]->dynamic_data_of (0)), (size_t)(64 * 1024 * 1024)), get_alignment_constant (TRUE));
gc_heap::dynamic_heap_count_data.min_gen0_new_allocation = Align (dd_min_size (gc_heap::g_heaps[0]->dynamic_data_of (0)), get_alignment_constant (TRUE));

dprintf (6666, ("datas max gen0 budget %Id, min %Id",
gc_heap::dynamic_heap_count_data.max_gen0_new_allocation, gc_heap::dynamic_heap_count_data.min_gen0_new_allocation));
int gen0_growth_soh_ratio_percent = (int)GCConfig::GetGCDGen0GrowthPercent();
if (gen0_growth_soh_ratio_percent)
{
gc_heap::dynamic_heap_count_data.gen0_growth_soh_ratio_percent = (int)GCConfig::GetGCDGen0GrowthPercent() * 0.01f;
}
// You can specify what sizes you want to allow DATAS to stay within wrt the SOH stable size.
// By default DATAS allows 10x this size for gen0 budget when the size is small, and 0.1x when the size is large.
int gen0_growth_min_permil = (int)GCConfig::GetGCDGen0GrowthMinFactor();
int gen0_growth_max_permil = (int)GCConfig::GetGCDGen0GrowthMaxFactor();
if (gen0_growth_min_permil)
{
gc_heap::dynamic_heap_count_data.gen0_growth_soh_ratio_min = gen0_growth_min_permil * 0.001f;
}
if (gen0_growth_max_permil)
{
gc_heap::dynamic_heap_count_data.gen0_growth_soh_ratio_max = gen0_growth_max_permil * 0.001f;
}

if (gc_heap::dynamic_heap_count_data.gen0_growth_soh_ratio_min > gc_heap::dynamic_heap_count_data.gen0_growth_soh_ratio_max)
{
log_init_error_to_host ("DATAS min permil for gen0 growth %d is greater than max %d, it needs to be lower",
gc_heap::dynamic_heap_count_data.gen0_growth_soh_ratio_min, gc_heap::dynamic_heap_count_data.gen0_growth_soh_ratio_max);
return E_FAIL;
}

GCConfig::SetGCDTargetTCP ((int)gc_heap::dynamic_heap_count_data.target_tcp);
GCConfig::SetGCDGen0GrowthPercent ((int)(gc_heap::dynamic_heap_count_data.gen0_growth_soh_ratio_percent * 100.0f));
GCConfig::SetGCDGen0GrowthMinFactor ((int)(gc_heap::dynamic_heap_count_data.gen0_growth_soh_ratio_min * 1000.0f));
GCConfig::SetGCDGen0GrowthMaxFactor ((int)(gc_heap::dynamic_heap_count_data.gen0_growth_soh_ratio_max * 1000.0f));
dprintf (6666, ("DATAS gen0 growth multiplier will be adjusted by %d%%, cap %.3f-%.3f, min budget %Id, max %Id",
(int)GCConfig::GetGCDGen0GrowthPercent(),
gc_heap::dynamic_heap_count_data.gen0_growth_soh_ratio_min, gc_heap::dynamic_heap_count_data.gen0_growth_soh_ratio_max,
gc_heap::dynamic_heap_count_data.min_gen0_new_allocation, gc_heap::dynamic_heap_count_data.max_gen0_new_allocation));
}

GCConfig::SetGCDynamicAdaptationMode (gc_heap::dynamic_adaptation_mode);
#endif //DYNAMIC_HEAP_COUNT
GCScan::GcRuntimeStructuresValid (TRUE);

Expand Down Expand Up @@ -52280,13 +52325,11 @@ size_t gc_heap::get_gen0_min_size()
gen0size = gen0size / 8 * 5;
}

#ifdef USE_REGIONS
#ifdef STRESS_REGIONS
// This is just so we can test allocation using more than one region on machines with very
// small caches.
gen0size = ((size_t)1 << min_segment_size_shr) * 3;
#endif //STRESS_REGIONS
#endif //USE_REGIONS

gen0size = Align (gen0size);

Expand Down Expand Up @@ -53883,6 +53926,8 @@ bool gc_heap::compute_memory_settings(bool is_initialization, uint32_t& nhp, uin
m_high_memory_load_th = min ((high_memory_load_th + 5), v_high_memory_load_th);
almost_high_memory_load_th = (high_memory_load_th > 5) ? (high_memory_load_th - 5) : 1; // avoid underflow of high_memory_load_th - 5

GCConfig::SetGCHighMemPercent (high_memory_load_th);

return true;
}

Expand Down
5 changes: 4 additions & 1 deletion src/coreclr/gc/gcconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class GCConfigStringHolder
"prefixed by the CPU group number. Example: Unix - 1,3,5,7-9,12, Windows - 0:1,1:7-9") \
INT_CONFIG (GCHighMemPercent, "GCHighMemPercent", "System.GC.HighMemoryPercent", 0, "The percent for GC to consider as high memory") \
INT_CONFIG (GCProvModeStress, "GCProvModeStress", NULL, 0, "Stress the provisional modes") \
INT_CONFIG (GCGen0MaxBudget, "GCGen0MaxBudget", NULL, 0, "Specifies the largest gen0 allocation budget") \
INT_CONFIG (GCGen0MaxBudget, "GCGen0MaxBudget", "System.GC.Gen0MaxBudget", 0, "Specifies the largest gen0 allocation budget") \
INT_CONFIG (GCGen1MaxBudget, "GCGen1MaxBudget", NULL, 0, "Specifies the largest gen1 allocation budget") \
INT_CONFIG (GCLowSkipRatio, "GCLowSkipRatio", NULL, 30, "Specifies the low generation skip ratio") \
INT_CONFIG (GCHeapHardLimit, "GCHeapHardLimit", "System.GC.HeapHardLimit", 0, "Specifies a hard limit for the GC heap") \
Expand Down Expand Up @@ -144,6 +144,9 @@ class GCConfigStringHolder
INT_CONFIG (GCDynamicAdaptationMode, "GCDynamicAdaptationMode", "System.GC.DynamicAdaptationMode", 1, "Enable the GC to dynamically adapt to application sizes.") \
INT_CONFIG (GCDTargetTCP, "GCDTargetTCP", "System.GC.DTargetTCP", 0, "Specifies the target tcp for DATAS") \
INT_CONFIG (GCDBGCRatio, "GCDBGCRatio", NULL, 0, "Specifies the ratio of BGC to NGC2 for HC change") \
INT_CONFIG (GCDGen0GrowthPercent, "GCDGen0GrowthPercent", "System.GC.DGen0GrowthPercent", 0, "Specifies the percentage of the default growth factor") \
INT_CONFIG (GCDGen0GrowthMinFactor, "GCDGen0GrowthMinFactor", "System.GC.DGen0GrowthMinFactor", 0, "Specifies the minimum growth factor in permil") \
INT_CONFIG (GCDGen0GrowthMaxFactor, "GCDGen0GrowthMaxFactor", "System.GC.DGen0GrowthMaxFactor", 0, "Specifies the maximum growth factor in permil") \
BOOL_CONFIG (GCCacheSizeFromSysConf, "GCCacheSizeFromSysConf", NULL, false, "Specifies using sysconf to retrieve the last level cache size for Unix.")

// This class is responsible for retreiving configuration information
Expand Down
30 changes: 21 additions & 9 deletions src/coreclr/gc/gcpriv.h
Original file line number Diff line number Diff line change
Expand Up @@ -4388,6 +4388,18 @@ class gc_heap
float target_tcp = 2.0;
float target_gen2_tcp = 10.0;

// The following 3 constants are used in the computation for the total gen0 budget relative to the stable soh size.
//
// By default DATAS computes a multiplier (gen0_growth_soh_ratio) that scales the size. This multiplier follows
// a power decay curve where the multiplier decreases rapidly as the size increases. We cap it at 10x at the low
// end and 10% at the high end.
//
// You can choose to modify these by specifying gen0_growth_factor_percent to reduce or increase this multiplier
// and the min/max multipliers.
float gen0_growth_soh_ratio_percent = 1.0;
float gen0_growth_soh_ratio_min = 0.1f;
float gen0_growth_soh_ratio_max = 10.0;

static const int recorded_adjustment_size = 4;
static const int sample_size = 3;
static const int recorded_tcp_array_size = 64;
Expand Down Expand Up @@ -5069,23 +5081,23 @@ class gc_heap
// time in msl).
//

size_t max_gen0_new_allocation;
size_t min_gen0_new_allocation;
size_t max_gen0_new_allocation = 64 * 1024 * 1024;
size_t min_gen0_new_allocation = 0;

size_t compute_total_gen0_budget (size_t total_soh_stable_size)
{
assert (total_soh_stable_size > 0);

float factor = (float)(20 - conserve_mem_setting);
double old_gen_growth_factor = factor / sqrt ((double)total_soh_stable_size / 1000.0 / 1000.0);
double saved_old_gen_growth_factor = old_gen_growth_factor;
old_gen_growth_factor = min (10.0, old_gen_growth_factor);
old_gen_growth_factor = max (0.1, old_gen_growth_factor);
float factor = (float)(20 - conserve_mem_setting) * gen0_growth_soh_ratio_percent;
double gen0_growth_soh_ratio = factor / sqrt ((double)total_soh_stable_size / 1000.0 / 1000.0);
double saved_gen0_growth_soh_ratio = gen0_growth_soh_ratio;
gen0_growth_soh_ratio = min ((double)gen0_growth_soh_ratio_max, gen0_growth_soh_ratio);
gen0_growth_soh_ratio = max ((double)gen0_growth_soh_ratio_min, gen0_growth_soh_ratio);

size_t total_new_allocation_old_gen = (size_t)(old_gen_growth_factor * (double)total_soh_stable_size);
size_t total_new_allocation_old_gen = (size_t)(gen0_growth_soh_ratio * (double)total_soh_stable_size);
dprintf (6666, ("stable soh %Id (%.3fmb), factor %.3f=>%.3f -> total gen0 new_alloc %Id (%.3fmb)",
total_soh_stable_size, ((double)total_soh_stable_size / 1000.0 / 1000.0),
saved_old_gen_growth_factor, old_gen_growth_factor, total_new_allocation_old_gen,
saved_gen0_growth_soh_ratio, gen0_growth_soh_ratio, total_new_allocation_old_gen,
((double)total_new_allocation_old_gen / 1000.0 / 1000.0)));
return total_new_allocation_old_gen;
}
Expand Down
Loading