Skip to content

Commit 6347f10

Browse files
author
William Kemper
committed
8370521: GenShen: Various code cleanup related to promotion
Reviewed-by: fandreuzzi, kdnilsen, ysr
1 parent 3c1010b commit 6347f10

12 files changed

+65
-57
lines changed

src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ bool ShenandoahOldHeuristics::prime_collection_set(ShenandoahCollectionSet* coll
141141
// If region r is evacuated to fragmented memory (to free memory within a partially used region), then we need
142142
// to decrease the capacity of the fragmented memory by the scaled loss.
143143

144-
size_t live_data_for_evacuation = r->get_live_data_bytes();
144+
const size_t live_data_for_evacuation = r->get_live_data_bytes();
145145
size_t lost_available = r->free();
146146

147147
if ((lost_available > 0) && (excess_fragmented_available > 0)) {
@@ -169,7 +169,9 @@ bool ShenandoahOldHeuristics::prime_collection_set(ShenandoahCollectionSet* coll
169169
// We were not able to account for the lost free memory within fragmented memory, so we need to take this
170170
// allocation out of unfragmented memory. Unfragmented memory does not need to account for loss of free.
171171
if (live_data_for_evacuation > unfragmented_available) {
172-
// There is not room to evacuate this region or any that come after it in within the candidates array.
172+
// There is no room to evacuate this region or any that come after it in within the candidates array.
173+
log_debug(gc, cset)("Not enough unfragmented memory (%zu) to hold evacuees (%zu) from region: (%zu)",
174+
unfragmented_available, live_data_for_evacuation, r->index());
173175
break;
174176
} else {
175177
unfragmented_available -= live_data_for_evacuation;
@@ -187,7 +189,9 @@ bool ShenandoahOldHeuristics::prime_collection_set(ShenandoahCollectionSet* coll
187189
evacuation_need = 0;
188190
}
189191
if (evacuation_need > unfragmented_available) {
190-
// There is not room to evacuate this region or any that come after it in within the candidates array.
192+
// There is no room to evacuate this region or any that come after it in within the candidates array.
193+
log_debug(gc, cset)("Not enough unfragmented memory (%zu) to hold evacuees (%zu) from region: (%zu)",
194+
unfragmented_available, live_data_for_evacuation, r->index());
191195
break;
192196
} else {
193197
unfragmented_available -= evacuation_need;

src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,9 @@ void ShenandoahCollectionSet::summarize(size_t total_garbage, size_t immediate_g
225225
count());
226226

227227
if (garbage() > 0) {
228-
const size_t young_evac_bytes = get_young_bytes_reserved_for_evacuation();
229-
const size_t promote_evac_bytes = get_young_bytes_to_be_promoted();
230-
const size_t old_evac_bytes = get_old_bytes_reserved_for_evacuation();
228+
const size_t young_evac_bytes = get_live_bytes_in_untenurable_regions();
229+
const size_t promote_evac_bytes = get_live_bytes_in_tenurable_regions();
230+
const size_t old_evac_bytes = get_live_bytes_in_old_regions();
231231
const size_t total_evac_bytes = young_evac_bytes + promote_evac_bytes + old_evac_bytes;
232232
ls.print_cr("Evacuation Targets: "
233233
"YOUNG: " PROPERFMT ", " "PROMOTE: " PROPERFMT ", " "OLD: " PROPERFMT ", " "TOTAL: " PROPERFMT,

src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,14 @@ class ShenandoahCollectionSet : public CHeapObj<mtGC> {
109109
// Prints a summary of the collection set when gc+ergo=info
110110
void summarize(size_t total_garbage, size_t immediate_garbage, size_t immediate_regions) const;
111111

112-
// Returns the amount of live bytes in young regions in the collection set. It is not known how many of these bytes will be promoted.
113-
inline size_t get_young_bytes_reserved_for_evacuation() const;
112+
// Returns the amount of live bytes in young regions with an age below the tenuring threshold.
113+
inline size_t get_live_bytes_in_untenurable_regions() const;
114114

115115
// Returns the amount of live bytes in old regions in the collection set.
116-
inline size_t get_old_bytes_reserved_for_evacuation() const;
116+
inline size_t get_live_bytes_in_old_regions() const;
117117

118-
// Returns the amount of live bytes in young regions with an age above the tenuring threshold.
119-
inline size_t get_young_bytes_to_be_promoted() const;
118+
// Returns the amount of live bytes in young regions with an age at or above the tenuring threshold.
119+
inline size_t get_live_bytes_in_tenurable_regions() const;
120120

121121
// Returns the amount of free bytes in young regions in the collection set.
122122
size_t get_young_available_bytes_collected() const { return _young_available_bytes_collected; }
@@ -125,7 +125,7 @@ class ShenandoahCollectionSet : public CHeapObj<mtGC> {
125125
inline size_t get_old_garbage() const;
126126

127127
bool is_preselected(size_t region_idx) {
128-
assert(_preselected_regions != nullptr, "Missing etsablish after abandon");
128+
assert(_preselected_regions != nullptr, "Missing establish after abandon");
129129
return _preselected_regions[region_idx];
130130
}
131131

src/hotspot/share/gc/shenandoah/shenandoahCollectionSet.inline.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,15 @@ bool ShenandoahCollectionSet::is_in_loc(void* p) const {
5454
return _biased_cset_map[index] == 1;
5555
}
5656

57-
size_t ShenandoahCollectionSet::get_old_bytes_reserved_for_evacuation() const {
57+
size_t ShenandoahCollectionSet::get_live_bytes_in_old_regions() const {
5858
return _old_bytes_to_evacuate;
5959
}
6060

61-
size_t ShenandoahCollectionSet::get_young_bytes_reserved_for_evacuation() const {
61+
size_t ShenandoahCollectionSet::get_live_bytes_in_untenurable_regions() const {
6262
return _young_bytes_to_evacuate - _young_bytes_to_promote;
6363
}
6464

65-
size_t ShenandoahCollectionSet::get_young_bytes_to_be_promoted() const {
65+
size_t ShenandoahCollectionSet::get_live_bytes_in_tenurable_regions() const {
6666
return _young_bytes_to_promote;
6767
}
6868

src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -382,11 +382,11 @@ void ShenandoahGeneration::adjust_evacuation_budgets(ShenandoahHeap* const heap,
382382
// available that results from a decrease in memory consumed by old evacuation is not necessarily available to be loaned
383383
// to young-gen.
384384

385-
size_t region_size_bytes = ShenandoahHeapRegion::region_size_bytes();
385+
const size_t region_size_bytes = ShenandoahHeapRegion::region_size_bytes();
386386
ShenandoahOldGeneration* const old_generation = heap->old_generation();
387387
ShenandoahYoungGeneration* const young_generation = heap->young_generation();
388388

389-
size_t old_evacuated = collection_set->get_old_bytes_reserved_for_evacuation();
389+
const size_t old_evacuated = collection_set->get_live_bytes_in_old_regions();
390390
size_t old_evacuated_committed = (size_t) (ShenandoahOldEvacWaste * double(old_evacuated));
391391
size_t old_evacuation_reserve = old_generation->get_evacuation_reserve();
392392

@@ -399,14 +399,15 @@ void ShenandoahGeneration::adjust_evacuation_budgets(ShenandoahHeap* const heap,
399399
// Leave old_evac_reserve as previously configured
400400
} else if (old_evacuated_committed < old_evacuation_reserve) {
401401
// This happens if the old-gen collection consumes less than full budget.
402+
log_debug(gc, cset)("Shrinking old evac reserve to match old_evac_commited: " PROPERFMT, PROPERFMTARGS(old_evacuated_committed));
402403
old_evacuation_reserve = old_evacuated_committed;
403404
old_generation->set_evacuation_reserve(old_evacuation_reserve);
404405
}
405406

406-
size_t young_advance_promoted = collection_set->get_young_bytes_to_be_promoted();
407+
size_t young_advance_promoted = collection_set->get_live_bytes_in_tenurable_regions();
407408
size_t young_advance_promoted_reserve_used = (size_t) (ShenandoahPromoEvacWaste * double(young_advance_promoted));
408409

409-
size_t young_evacuated = collection_set->get_young_bytes_reserved_for_evacuation();
410+
size_t young_evacuated = collection_set->get_live_bytes_in_untenurable_regions();
410411
size_t young_evacuated_reserve_used = (size_t) (ShenandoahEvacWaste * double(young_evacuated));
411412

412413
size_t total_young_available = young_generation->available_with_reserve();
@@ -524,7 +525,7 @@ inline void assert_no_in_place_promotions() {
524525
// that this allows us to more accurately budget memory to hold the results of evacuation. Memory for evacuation
525526
// of aged regions must be reserved in the old generation. Memory for evacuation of all other regions must be
526527
// reserved in the young generation.
527-
size_t ShenandoahGeneration::select_aged_regions(size_t old_available) {
528+
size_t ShenandoahGeneration::select_aged_regions(const size_t old_promotion_reserve) {
528529

529530
// There should be no regions configured for subsequent in-place-promotions carried over from the previous cycle.
530531
assert_no_in_place_promotions();
@@ -537,7 +538,6 @@ size_t ShenandoahGeneration::select_aged_regions(size_t old_available) {
537538

538539
const size_t pip_used_threshold = (ShenandoahHeapRegion::region_size_bytes() * ShenandoahGenerationalMinPIPUsage) / 100;
539540

540-
size_t old_consumed = 0;
541541
size_t promo_potential = 0;
542542
size_t candidates = 0;
543543

@@ -560,7 +560,7 @@ size_t ShenandoahGeneration::select_aged_regions(size_t old_available) {
560560
}
561561
if (heap->is_tenurable(r)) {
562562
if ((r->garbage() < old_garbage_threshold) && (r->used() > pip_used_threshold)) {
563-
// We prefer to promote this region in place because is has a small amount of garbage and a large usage.
563+
// We prefer to promote this region in place because it has a small amount of garbage and a large usage.
564564
HeapWord* tams = ctx->top_at_mark_start(r);
565565
HeapWord* original_top = r->top();
566566
if (!heap->is_concurrent_old_mark_in_progress() && tams == original_top) {
@@ -620,17 +620,21 @@ size_t ShenandoahGeneration::select_aged_regions(size_t old_available) {
620620
// Note that we keep going even if one region is excluded from selection.
621621
// Subsequent regions may be selected if they have smaller live data.
622622
}
623+
624+
log_info(gc, ergo)("Promotion potential of aged regions with sufficient garbage: " PROPERFMT, PROPERFMTARGS(promo_potential));
625+
623626
// Sort in increasing order according to live data bytes. Note that candidates represents the number of regions
624627
// that qualify to be promoted by evacuation.
628+
size_t old_consumed = 0;
625629
if (candidates > 0) {
626630
size_t selected_regions = 0;
627631
size_t selected_live = 0;
628632
QuickSort::sort<AgedRegionData>(sorted_regions, candidates, compare_by_aged_live);
629633
for (size_t i = 0; i < candidates; i++) {
630634
ShenandoahHeapRegion* const region = sorted_regions[i]._region;
631-
size_t region_live_data = sorted_regions[i]._live_data;
632-
size_t promotion_need = (size_t) (region_live_data * ShenandoahPromoEvacWaste);
633-
if (old_consumed + promotion_need <= old_available) {
635+
const size_t region_live_data = sorted_regions[i]._live_data;
636+
const size_t promotion_need = (size_t) (region_live_data * ShenandoahPromoEvacWaste);
637+
if (old_consumed + promotion_need <= old_promotion_reserve) {
634638
old_consumed += promotion_need;
635639
candidate_regions_for_promotion_by_copy[region->index()] = true;
636640
selected_regions++;
@@ -644,9 +648,9 @@ size_t ShenandoahGeneration::select_aged_regions(size_t old_available) {
644648
// We keep going even if one region is excluded from selection because we need to accumulate all eligible
645649
// regions that are not preselected into promo_potential
646650
}
647-
log_debug(gc)("Preselected %zu regions containing %zu live bytes,"
648-
" consuming: %zu of budgeted: %zu",
649-
selected_regions, selected_live, old_consumed, old_available);
651+
log_debug(gc, ergo)("Preselected %zu regions containing " PROPERFMT " live data,"
652+
" consuming: " PROPERFMT " of budgeted: " PROPERFMT,
653+
selected_regions, PROPERFMTARGS(selected_live), PROPERFMTARGS(old_consumed), PROPERFMTARGS(old_promotion_reserve));
650654
}
651655

652656
heap->old_generation()->set_pad_for_promote_in_place(promote_in_place_pad);

src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ class ShenandoahGeneration : public CHeapObj<mtGC>, public ShenandoahSpaceInfo {
9797
// regions, which are marked in the preselected_regions() indicator
9898
// array of the heap's collection set, which should be initialized
9999
// to false.
100-
size_t select_aged_regions(size_t old_available);
100+
size_t select_aged_regions(size_t old_promotion_reserve);
101101

102102
size_t available(size_t capacity) const;
103103

src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ void ShenandoahGenerationalHeap::initialize_heuristics() {
110110
_generation_sizer.heap_size_changed(max_capacity());
111111
size_t initial_capacity_young = _generation_sizer.max_young_size();
112112
size_t max_capacity_young = _generation_sizer.max_young_size();
113-
size_t initial_capacity_old = max_capacity() - max_capacity_young;
114113
size_t max_capacity_old = max_capacity() - initial_capacity_young;
115114

116115
_young_generation = new ShenandoahYoungGeneration(max_workers(), max_capacity_young);
@@ -267,6 +266,7 @@ oop ShenandoahGenerationalHeap::try_evacuate_object(oop p, Thread* thread, Shena
267266
// the requested object does not fit within the current plab but the plab still has an "abundance" of memory,
268267
// where abundance is defined as >= ShenGenHeap::plab_min_size(). In the former case, we try shrinking the
269268
// desired PLAB size to the minimum and retry PLAB allocation to avoid cascading of shared memory allocations.
269+
// Shrinking the desired PLAB size may allow us to eke out a small PLAB while staying beneath evacuation reserve.
270270
if (plab->words_remaining() < plab_min_size()) {
271271
ShenandoahThreadLocalData::set_plab_size(thread, plab_min_size());
272272
copy = allocate_from_plab(thread, size, is_promotion);
@@ -436,9 +436,8 @@ inline HeapWord* ShenandoahGenerationalHeap::allocate_from_plab(Thread* thread,
436436

437437
// Establish a new PLAB and allocate size HeapWords within it.
438438
HeapWord* ShenandoahGenerationalHeap::allocate_from_plab_slow(Thread* thread, size_t size, bool is_promotion) {
439-
// New object should fit the PLAB size
440-
441439
assert(mode()->is_generational(), "PLABs only relevant to generational GC");
440+
442441
const size_t plab_min_size = this->plab_min_size();
443442
// PLABs are aligned to card boundaries to avoid synchronization with concurrent
444443
// allocations in other PLABs.
@@ -451,23 +450,24 @@ HeapWord* ShenandoahGenerationalHeap::allocate_from_plab_slow(Thread* thread, si
451450
}
452451

453452
// Expand aggressively, doubling at each refill in this epoch, ceiling at plab_max_size()
454-
size_t future_size = MIN2(cur_size * 2, plab_max_size());
453+
const size_t future_size = MIN2(cur_size * 2, plab_max_size());
455454
// Doubling, starting at a card-multiple, should give us a card-multiple. (Ceiling and floor
456455
// are card multiples.)
457456
assert(is_aligned(future_size, CardTable::card_size_in_words()), "Card multiple by construction, future_size: %zu"
458-
", card_size: %zu, cur_size: %zu, max: %zu",
459-
future_size, (size_t) CardTable::card_size_in_words(), cur_size, plab_max_size());
457+
", card_size: %u, cur_size: %zu, max: %zu",
458+
future_size, CardTable::card_size_in_words(), cur_size, plab_max_size());
460459

461460
// Record new heuristic value even if we take any shortcut. This captures
462461
// the case when moderately-sized objects always take a shortcut. At some point,
463462
// heuristics should catch up with them. Note that the requested cur_size may
464463
// not be honored, but we remember that this is the preferred size.
465-
log_debug(gc, free)("Set new PLAB size: %zu", future_size);
464+
log_debug(gc, plab)("Set next PLAB refill size: %zu bytes", future_size * HeapWordSize);
466465
ShenandoahThreadLocalData::set_plab_size(thread, future_size);
466+
467467
if (cur_size < size) {
468468
// The PLAB to be allocated is still not large enough to hold the object. Fall back to shared allocation.
469469
// This avoids retiring perfectly good PLABs in order to represent a single large object allocation.
470-
log_debug(gc, free)("Current PLAB size (%zu) is too small for %zu", cur_size, size);
470+
log_debug(gc, plab)("Current PLAB size (%zu) is too small for %zu", cur_size * HeapWordSize, size * HeapWordSize);
471471
return nullptr;
472472
}
473473

@@ -553,6 +553,7 @@ void ShenandoahGenerationalHeap::retire_plab(PLAB* plab, Thread* thread) {
553553
ShenandoahThreadLocalData::reset_plab_promoted(thread);
554554
ShenandoahThreadLocalData::set_plab_actual_size(thread, 0);
555555
if (not_promoted > 0) {
556+
log_debug(gc, plab)("Retire PLAB, unexpend unpromoted: %zu", not_promoted * HeapWordSize);
556557
old_generation()->unexpend_promoted(not_promoted);
557558
}
558559
const size_t original_waste = plab->waste();
@@ -564,8 +565,8 @@ void ShenandoahGenerationalHeap::retire_plab(PLAB* plab, Thread* thread) {
564565
if (top != nullptr && plab->waste() > original_waste && is_in_old(top)) {
565566
// If retiring the plab created a filler object, then we need to register it with our card scanner so it can
566567
// safely walk the region backing the plab.
567-
log_debug(gc)("retire_plab() is registering remnant of size %zu at " PTR_FORMAT,
568-
plab->waste() - original_waste, p2i(top));
568+
log_debug(gc, plab)("retire_plab() is registering remnant of size %zu at " PTR_FORMAT,
569+
(plab->waste() - original_waste) * HeapWordSize, p2i(top));
569570
// No lock is necessary because the PLAB memory is aligned on card boundaries.
570571
old_generation()->card_scan()->register_object_without_lock(top);
571572
}

src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1271,7 +1271,7 @@ void ShenandoahHeap::evacuate_collection_set(ShenandoahGeneration* generation, b
12711271

12721272
void ShenandoahHeap::concurrent_prepare_for_update_refs() {
12731273
{
1274-
// Java threads take this lock while they are being attached and added to the list of thread.
1274+
// Java threads take this lock while they are being attached and added to the list of threads.
12751275
// If another thread holds this lock before we update the gc state, it will receive a stale
12761276
// gc state, but they will have been added to the list of java threads and so will be corrected
12771277
// by the following handshake.

src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,6 @@ void ShenandoahOldGC::op_final_mark() {
6969
heap->set_unload_classes(false);
7070
heap->prepare_concurrent_roots();
7171

72-
// Believe verification following old-gen concurrent mark needs to be different than verification following
73-
// young-gen concurrent mark, so am commenting this out for now:
74-
// if (ShenandoahVerify) {
75-
// heap->verifier()->verify_after_concmark();
76-
// }
77-
7872
if (VerifyAfterGC) {
7973
Universe::verify();
8074
}

src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,16 +303,21 @@ ShenandoahOldGeneration::configure_plab_for_current_thread(const ShenandoahAlloc
303303
if (can_promote(actual_size)) {
304304
// Assume the entirety of this PLAB will be used for promotion. This prevents promotion from overreach.
305305
// When we retire this plab, we'll unexpend what we don't really use.
306+
log_debug(gc, plab)("Thread can promote using PLAB of %zu bytes. Expended: %zu, available: %zu",
307+
actual_size, get_promoted_expended(), get_promoted_reserve());
306308
expend_promoted(actual_size);
307309
ShenandoahThreadLocalData::enable_plab_promotions(thread);
308310
ShenandoahThreadLocalData::set_plab_actual_size(thread, actual_size);
309311
} else {
310312
// Disable promotions in this thread because entirety of this PLAB must be available to hold old-gen evacuations.
311313
ShenandoahThreadLocalData::disable_plab_promotions(thread);
312314
ShenandoahThreadLocalData::set_plab_actual_size(thread, 0);
315+
log_debug(gc, plab)("Thread cannot promote using PLAB of %zu bytes. Expended: %zu, available: %zu, mixed evacuations? %s",
316+
actual_size, get_promoted_expended(), get_promoted_reserve(), BOOL_TO_STR(ShenandoahHeap::heap()->collection_set()->has_old_regions()));
313317
}
314318
} else if (req.is_promotion()) {
315319
// Shared promotion.
320+
log_debug(gc, plab)("Expend shared promotion of %zu bytes", actual_size);
316321
expend_promoted(actual_size);
317322
}
318323
}

0 commit comments

Comments
 (0)