diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index e04b77284d8394..7d24f55b4fb37e 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -44894,10 +44894,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); @@ -45044,7 +45054,30 @@ 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. + if ((gc_heap::regions_range / nhp / min_regions_per_heap) / 2 >= (4 * 1024 * 1024)) + { + gc_region_size = 4 * 1024 * 1024; + } + else if ((gc_heap::regions_range / nhp / min_regions_per_heap) / 2 >= (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 df4ce12ec529e1..37e69af1e023ee 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,