Optimize region count (#56471)
authorPeter Sollich <petersol@microsoft.com>
Fri, 30 Jul 2021 07:05:34 +0000 (09:05 +0200)
committerGitHub <noreply@github.com>
Fri, 30 Jul 2021 07:05:34 +0000 (09:05 +0200)
We have a couple of arrays with an entry per region - instead of iterating over all the regions that we have reserved address space for, iterate just over the regions actually in use.

Arrays affected by this are mark_list_piece_start, mark_list_piece_end, survived_per_region and old_card_survived per_region.

To avoid having inconsistent counts, we get the count of regions actually in use at the start of mark_phase. Any regions added during GC should not matter, because they shouldn't contain any marked objects.

While the region allocator has provisions to allocate regions from the highest addresses down, we don't use that facility now. If we do, the code to iterate through the used regions will need to get more sophisticated. I put an assert that would fire in this case.

src/coreclr/gc/gc.cpp
src/coreclr/gc/gcpriv.h

index 8211cb991f69869e8c97da2d732bb69d2f24c109..0646b3b826d100bb81066dae3dc378dbd0c69d21 100644 (file)
@@ -2295,6 +2295,7 @@ bool        affinity_config_specified_p = false;
 #ifdef USE_REGIONS
 region_allocator global_region_allocator;
 uint8_t*(*initial_regions)[total_generation_count][2] = nullptr;
+size_t      gc_heap::region_count = 0;
 #endif //USE_REGIONS
 
 #ifdef BACKGROUND_GC
@@ -3512,12 +3513,6 @@ size_t get_basic_region_index_for_address (uint8_t* address)
     return (basic_region_index - ((size_t)g_gc_lowest_address >> gc_heap::min_segment_size_shr));
 }
 
-inline
-size_t get_total_region_count()
-{
-    return (get_basic_region_index_for_address (g_gc_highest_address) + 1);
-}
-
 // Go from a random address to its region info. The random address could be 
 // in one of the basic regions of a larger region so we need to check for that.
 inline
@@ -9741,7 +9736,6 @@ size_t gc_heap::sort_mark_list()
 
 #ifdef USE_REGIONS
     // first set the pieces for all regions to empty
-    size_t region_count = get_total_region_count();
     assert (g_mark_list_piece_size >= region_count);
     for (size_t region_index = 0; region_index < region_count; region_index++)
     {
@@ -21140,7 +21134,6 @@ size_t gc_heap::get_promoted_bytes()
     }
 
     dprintf (3, ("h%d getting surv", heap_number));
-    size_t region_count = get_total_region_count();
     size_t promoted = 0;
     for (size_t i = 0; i < region_count; i++)
     {
@@ -23936,6 +23929,7 @@ void gc_heap::mark_phase (int condemned_gen_number, BOOL mark_only_p)
 
 #ifdef USE_REGIONS
         special_sweep_p = false;
+        region_count = global_region_allocator.get_used_region_count();
         grow_mark_list_piece();
 #endif //USE_REGIONS
 
@@ -24004,7 +23998,7 @@ void gc_heap::mark_phase (int condemned_gen_number, BOOL mark_only_p)
 #endif //MULTIPLE_HEAPS
             survived_per_region = (size_t*)&g_mark_list_piece[heap_number * 2 * g_mark_list_piece_size];
             old_card_survived_per_region = (size_t*)&survived_per_region[g_mark_list_piece_size];
-            size_t region_info_to_clear = get_total_region_count() * sizeof (size_t);
+            size_t region_info_to_clear = region_count * sizeof (size_t);
             memset (survived_per_region, 0, region_info_to_clear);
             memset (old_card_survived_per_region, 0, region_info_to_clear);
         }
@@ -26215,7 +26209,6 @@ void gc_heap::process_remaining_regions (int current_plan_gen_num, generation* c
 
 void gc_heap::grow_mark_list_piece()
 {
-    size_t region_count = get_total_region_count();
     if (g_mark_list_piece_size < region_count)
     {
         delete[] g_mark_list_piece;
@@ -26240,11 +26233,10 @@ void gc_heap::save_current_survived()
 {
     if (!survived_per_region) return;
 
-    size_t region_info_to_copy = get_total_region_count() * sizeof (size_t);
+    size_t region_info_to_copy = region_count * sizeof (size_t);
     memcpy (old_card_survived_per_region, survived_per_region, region_info_to_copy);
 
 #ifdef _DEBUG
-    size_t region_count = get_total_region_count();
     for (size_t region_index = 0; region_index < region_count; region_index++)
     {
         if (survived_per_region[region_index] != 0)
@@ -26261,7 +26253,6 @@ void gc_heap::update_old_card_survived()
 {
     if (!survived_per_region) return;
 
-    size_t region_count = get_total_region_count();
     for (size_t region_index = 0; region_index < region_count; region_index++)
     {
         old_card_survived_per_region[region_index] = survived_per_region[region_index] - 
index 81dcc1fc0e088b6a9f11963598469397c157d7c6..36a1e8326aff72ee76017855f2fc2b8ef44b6db0 100644 (file)
@@ -3585,6 +3585,8 @@ public:
     size_t* survived_per_region;
     PER_HEAP
     size_t* old_card_survived_per_region;
+    PER_HEAP_ISOLATED
+    size_t region_count;
 #endif //USE_REGIONS
 
 #define max_oom_history_count 4
@@ -5700,6 +5702,14 @@ public:
     size_t get_free() { return (total_free_units * region_alignment) ; }
     size_t get_region_alignment () { return region_alignment; }
     size_t get_large_region_alignment () { return large_region_alignment; }
+    size_t get_used_region_count()
+    {
+        // currently we don't allocate anything from the right -
+        // once we do, we need a more sophisticated way to iterate
+        // through the used regions
+        assert (region_map_right_start == region_map_right_end);
+        return (region_map_left_end - region_map_left_start);
+    }
 };
 #endif //USE_REGIONS