-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[draft] [GC] Don't promote gen0 when it is mostly objects moved to the finalization queue #109085
Changes from 5 commits
88a4e9b
f862654
0f97e17
e802e9c
115ab2b
d0e5858
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2966,6 +2966,7 @@ dynamic_data gc_heap::dynamic_data_table [total_generation_count]; | |
gc_history_per_heap gc_heap::gc_data_per_heap; | ||
size_t gc_heap::total_promoted_bytes = 0; | ||
size_t gc_heap::finalization_promoted_bytes = 0; | ||
bool gc_heap::high_finalization_percentage = false; | ||
size_t gc_heap::maxgen_pinned_compact_before_advance = 0; | ||
|
||
uint8_t* gc_heap::alloc_allocated = 0; | ||
|
@@ -29535,12 +29536,13 @@ BOOL gc_heap::decide_on_promotion_surv (size_t threshold) | |
size_t older_gen_size = dd_current_size (dd) + (dd_desired_allocation (dd) - dd_new_allocation (dd)); | ||
|
||
size_t promoted = hp->total_promoted_bytes; | ||
bool do_promote = ((threshold > older_gen_size) || (promoted > threshold)); | ||
|
||
dprintf (6666, ("h%d promotion threshold: %zd, promoted bytes: %zd size n+1: %zd -> %s", | ||
i, threshold, promoted, older_gen_size, | ||
(((threshold > (older_gen_size)) || (promoted > threshold)) ? "promote" : "don't promote"))); | ||
(do_promote ? "promote" : "don't promote"))); | ||
|
||
if ((threshold > (older_gen_size)) || (promoted > threshold)) | ||
if (do_promote) | ||
{ | ||
return TRUE; | ||
} | ||
|
@@ -30230,6 +30232,7 @@ void gc_heap::mark_phase (int condemned_gen_number) | |
#endif //FEATURE_PREMORTEM_FINALIZATION | ||
|
||
total_promoted_bytes = get_promoted_bytes(); | ||
finalization_promoted_bytes = total_promoted_bytes - promoted_bytes_live; | ||
|
||
#ifdef MULTIPLE_HEAPS | ||
static VOLATILE(int32_t) syncblock_scan_p; | ||
|
@@ -30280,7 +30283,11 @@ void gc_heap::mark_phase (int condemned_gen_number) | |
#endif //FEATURE_EVENT_TRACE | ||
|
||
//decide on promotion | ||
if (!settings.promotion) | ||
int finalization_percent = (total_promoted_bytes > 0) | ||
? static_cast<int>((100 * finalization_promoted_bytes) / total_promoted_bytes) : 0; | ||
dprintf (6666, ("finalization promotion: %d%% (%zd / %zd)", finalization_percent, finalization_promoted_bytes, total_promoted_bytes)); | ||
high_finalization_percentage = finalization_percent >= 90; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 90? Microbenchmark is showing 95-98, so this works for it, but 90 is awfully high. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 6666 is probably not the right dprintf level here |
||
if (!settings.promotion && !high_finalization_percentage) | ||
{ | ||
size_t m = 0; | ||
for (int n = 0; n <= condemned_gen_number;n++) | ||
|
@@ -30360,8 +30367,6 @@ void gc_heap::mark_phase (int condemned_gen_number) | |
merge_mark_lists (total_mark_list_size); | ||
#endif //MULTIPLE_HEAPS && !USE_REGIONS | ||
|
||
finalization_promoted_bytes = total_promoted_bytes - promoted_bytes_live; | ||
|
||
mark_queue.verify_empty(); | ||
|
||
dprintf(2,("---- End of mark phase ----")); | ||
|
@@ -45045,6 +45050,11 @@ BOOL gc_heap::decide_on_compacting (int condemned_gen_number, | |
should_compact = TRUE; | ||
} | ||
|
||
if (high_finalization_percentage) | ||
{ | ||
should_compact = TRUE; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. currently not-compacting causes us to enable promotion below |
||
} | ||
|
||
dprintf (2, ("Fragmentation: %zu Fragmentation burden %d%%", | ||
fragmentation, (int) (100*fragmentation_burden))); | ||
|
||
|
@@ -52176,6 +52186,19 @@ void CFinalize::WalkFReachableObjects (fq_walk_fn fn) | |
} | ||
} | ||
|
||
void CFinalize::LogCounts(const char* label) | ||
{ | ||
size_t genCounts[max_generation + 1] = {}; | ||
for (int gen = 0; gen <= max_generation; ++gen) | ||
{ | ||
unsigned int seg = gen_segment(gen); | ||
genCounts[gen] = SegQueueCount(seg); | ||
} | ||
dprintf(1, ("Finalizer counts @%5s; 0: %6zu; 1: %6zu, 2: %6zu; CF: %6zu; F: %6zu; Free: %6zu", | ||
label, genCounts[0], genCounts[1], genCounts[2], | ||
SegQueueCount(CriticalFinalizerListSeg), SegQueueCount(FinalizerListSeg), SegQueueCount(FreeListSeg))); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Existing event only records how much is added to the finalization list. This lets us watch the size over time. I think this is probably worth a new event as well, but I haven't decided what it should be. (perhaps as minimal as just the "start" ones but only if something is non-zero?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. probably shouldn't be dprintf(1) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #ifdef There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add event for beginning of GC - add to HeapStats? |
||
|
||
BOOL | ||
CFinalize::ScanForFinalization (promote_func* pfn, int gen, gc_heap* hp) | ||
{ | ||
|
@@ -52189,6 +52212,8 @@ CFinalize::ScanForFinalization (promote_func* pfn, int gen, gc_heap* hp) | |
sc.thread_count = 1; | ||
#endif //MULTIPLE_HEAPS | ||
|
||
LogCounts("start"); | ||
|
||
BOOL finalizedFound = FALSE; | ||
|
||
//start with gen and explore all the younger generations. | ||
|
@@ -52279,6 +52304,8 @@ CFinalize::ScanForFinalization (promote_func* pfn, int gen, gc_heap* hp) | |
} | ||
} | ||
|
||
LogCounts("scan"); | ||
|
||
return finalizedFound; | ||
} | ||
|
||
|
@@ -52358,6 +52385,8 @@ CFinalize::UpdatePromotedGenerations (int gen, BOOL gen_0_empty_p) | |
} | ||
} | ||
} | ||
|
||
LogCounts("promo"); | ||
} | ||
|
||
BOOL | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -166,15 +166,22 @@ void GCHeap::UpdatePostGCCounters() | |
FIRE_EVENT(GCEnd_V1, static_cast<uint32_t>(pSettings->gc_index), condemned_gen); | ||
|
||
#ifdef SIMPLE_DPRINTF | ||
dprintf (2, ("GC#%zu: 0: %zu(%zu); 1: %zu(%zu); 2: %zu(%zu); 3: %zu(%zu)", | ||
dprintf (1, ("GC#%zu: 0: %zu(%zu); 1: %zu(%zu); 2: %zu(%zu); 3: %zu(%zu); 4: %zu(%zu); final: %zu bytes(%zu); pin: %zu; sync: %zu; gchandles: %zu", | ||
(size_t)pSettings->gc_index, | ||
g_GenerationSizes[0], g_GenerationPromotedSizes[0], | ||
g_GenerationSizes[1], g_GenerationPromotedSizes[1], | ||
g_GenerationSizes[2], g_GenerationPromotedSizes[2], | ||
g_GenerationSizes[3], g_GenerationPromotedSizes[3])); | ||
g_GenerationSizes[3], g_GenerationPromotedSizes[3], | ||
g_GenerationSizes[4], g_GenerationPromotedSizes[3], | ||
promoted_finalization_mem, | ||
GetFinalizablePromotedCount(), | ||
static_cast<uint32_t>(total_num_pinned_objects), | ||
total_num_sync_blocks, | ||
static_cast<uint32_t>(total_num_gc_handles))); | ||
#endif //SIMPLE_DPRINTF | ||
|
||
FIRE_EVENT(GCHeapStats_V2, | ||
FIRE_DPRINTF_EVENT(GCHeapStats_V2, 1, | ||
"0: %zu(%zu); 1: %zu(%zu); 2: %zu(%zu); 3: %zu(%zu); 4: %zu(%zu); final: %zu bytes(%zu); pin: %zu; sync: %zu; gchandles: %zu", | ||
Comment on lines
+168
to
+169
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. an idea for removing the code duplication here - This was useful to me because I was using other dprintfs (not an event log) to analyze this PR, but the checked-in dprintf was missing information that the event had. The downside is that one can't update the dprintf because it has to match the event. Notice that I had to drop the gc_index from the output, so one now has to go find the *GC* line. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. need to undo change to dprintf level 1 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cut |
||
g_GenerationSizes[0], g_GenerationPromotedSizes[0], | ||
g_GenerationSizes[1], g_GenerationPromotedSizes[1], | ||
g_GenerationSizes[2], g_GenerationPromotedSizes[2], | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
simple factoring from when I was initially changing this code