From bf83d79ca78fbedfc336210425db8feb12241ce4 Mon Sep 17 00:00:00 2001 From: Peter Sollich Date: Fri, 30 Jul 2021 09:05:34 +0200 Subject: [PATCH] Optimize region count (#56471) 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 | 17 ++++------------- src/coreclr/gc/gcpriv.h | 10 ++++++++++ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 8211cb991f698..0646b3b826d10 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -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] - diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index 81dcc1fc0e088..36a1e8326aff7 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -3585,6 +3585,8 @@ class gc_heap 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 @@ class region_allocator 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