diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index d603eda9ef2b0a..0f6318ba8f8cfc 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -44895,10 +44895,20 @@ HRESULT GCHeap::Initialize() { if (gc_heap::heap_hard_limit) { - gc_heap::regions_range = 2 * gc_heap::heap_hard_limit; + if (gc_heap::heap_hard_limit_oh[soh]) + { + gc_heap::regions_range = gc_heap::heap_hard_limit; + } + else + { + // We use this calculation because it's close to what we used for segments. + gc_heap::regions_range = ((gc_heap::use_large_pages_p) ? (2 * gc_heap::heap_hard_limit) + : (5 * gc_heap::heap_hard_limit)); + } } else { + // If no hard_limit is configured the reservation size is max of 256gb or 2x physical limit gc_heap::regions_range = max(((size_t)256 * 1024 * 1024 * 1024), (size_t)(2 * gc_heap::total_physical_mem)); } gc_heap::regions_range = align_on_page(gc_heap::regions_range); @@ -45049,7 +45059,31 @@ HRESULT GCHeap::Initialize() #ifdef USE_REGIONS gc_heap::enable_special_regions_p = (bool)GCConfig::GetGCEnableSpecialRegions(); size_t gc_region_size = (size_t)GCConfig::GetGCRegionSize(); - if (!power_of_two_p(gc_region_size) || ((gc_region_size * nhp * 19) > gc_heap::regions_range)) + + // Adjust GCRegionSize based on how large each heap would be, for smaller heaps we would + // like to keep Region sizes small. We choose between 4, 2 and 1mb based on the calculations + // below (unless its configured explictly) such that there are at least 2 regions available + // except for the smallest case. Now the lowest limit possible is 4mb. + if (gc_region_size == 0) + { + // We have a minimum amount of basic regions we have to fit per heap, and we'd like to have the initial + // regions only take up half of the space. + size_t max_region_size = gc_heap::regions_range / 2 / nhp / min_regions_per_heap; + if (max_region_size >= (4 * 1024 * 1024)) + { + gc_region_size = 4 * 1024 * 1024; + } + else if (max_region_size >= (2 * 1024 * 1024)) + { + gc_region_size = 2 * 1024 * 1024; + } + else + { + gc_region_size = 1 * 1024 * 1024; + } + } + + if (!power_of_two_p(gc_region_size) || ((gc_region_size * nhp * min_regions_per_heap) > gc_heap::regions_range)) { return E_OUTOFMEMORY; } diff --git a/src/coreclr/gc/gcconfig.h b/src/coreclr/gc/gcconfig.h index 532a6998c0bc6a..2b5f87b41f4cc3 100644 --- a/src/coreclr/gc/gcconfig.h +++ b/src/coreclr/gc/gcconfig.h @@ -104,7 +104,7 @@ class GCConfigStringHolder INT_CONFIG (GCHeapHardLimitPercent, "GCHeapHardLimitPercent", "System.GC.HeapHardLimitPercent", 0, "Specifies the GC heap usage as a percentage of the total memory") \ INT_CONFIG (GCTotalPhysicalMemory, "GCTotalPhysicalMemory", NULL, 0, "Specifies what the GC should consider to be total physical memory") \ INT_CONFIG (GCRegionRange, "GCRegionRange", NULL, 0, "Specifies the range for the GC heap") \ - INT_CONFIG (GCRegionSize, "GCRegionSize", NULL, 4194304, "Specifies the size for a basic GC region") \ + INT_CONFIG (GCRegionSize, "GCRegionSize", NULL, 0, "Specifies the size for a basic GC region") \ INT_CONFIG (GCEnableSpecialRegions, "GCEnableSpecialRegions", NULL, 0, "Specifies to enable special handling some regions like SIP") \ STRING_CONFIG(LogFile, "GCLogFile", NULL, "Specifies the name of the GC log file") \ STRING_CONFIG(ConfigLogFile, "GCConfigLogFile", NULL, "Specifies the name of the GC config log file") \ diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index 45f266259c62da..084fa0ba925d5b 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -5807,6 +5807,8 @@ class heap_segment #define region_alloc_free_bit (1 << (sizeof (uint32_t) * 8 - 1)) +const int min_regions_per_heap = ((ephemeral_generation_count + 1) + ((total_generation_count - uoh_start_generation) * LARGE_REGION_FACTOR)); + enum allocate_direction { allocate_forward = 1,