8367473: Shenandoah: Make the detailed evacuation metrics a runtime diagnostic option

8367722: [GenShen] ShenandoahEvacuationStats is always empty

Reviewed-by: ysr, phh
This commit is contained in:
William Kemper 2025-09-18 18:53:08 +00:00
parent 4be4826ddb
commit e4cb86df2b
5 changed files with 54 additions and 34 deletions

View File

@ -211,12 +211,11 @@ void ShenandoahControlThread::run_service() {
ResourceMark rm;
LogStream ls(lt);
heap->phase_timings()->print_cycle_on(&ls);
#ifdef NOT_PRODUCT
ShenandoahEvacuationTracker* evac_tracker = heap->evac_tracker();
ShenandoahCycleStats evac_stats = evac_tracker->flush_cycle_to_global();
evac_tracker->print_evacuations_on(&ls, &evac_stats.workers,
&evac_stats.mutators);
#endif
if (ShenandoahEvacTracking) {
ShenandoahEvacuationTracker* evac_tracker = heap->evac_tracker();
ShenandoahCycleStats evac_stats = evac_tracker->flush_cycle_to_global();
evac_tracker->print_evacuations_on(&ls, &evac_stats.workers, &evac_stats.mutators);
}
}
}

View File

@ -108,8 +108,10 @@ void ShenandoahEvacuationStats::ShenandoahEvacuations::print_on(outputStream* st
void ShenandoahEvacuationStats::print_on(outputStream* st) const {
st->print("Young: "); _young.print_on(st);
st->print("Promotion: "); _promotion.print_on(st);
st->print("Old: "); _old.print_on(st);
if (ShenandoahHeap::heap()->mode()->is_generational()) {
st->print("Promotion: "); _promotion.print_on(st);
st->print("Old: "); _old.print_on(st);
}
if (_use_age_table) {
_age_table->print_on(st);
@ -123,25 +125,28 @@ void ShenandoahEvacuationTracker::print_global_on(outputStream* st) {
void ShenandoahEvacuationTracker::print_evacuations_on(outputStream* st,
ShenandoahEvacuationStats* workers,
ShenandoahEvacuationStats* mutators) {
st->print_cr("Workers: ");
workers->print_on(st);
st->cr();
st->print_cr("Mutators: ");
mutators->print_on(st);
st->cr();
if (ShenandoahEvacTracking) {
st->print_cr("Workers: ");
workers->print_on(st);
st->cr();
st->print_cr("Mutators: ");
mutators->print_on(st);
st->cr();
}
ShenandoahHeap* heap = ShenandoahHeap::heap();
AgeTable young_region_ages(false);
for (uint i = 0; i < heap->num_regions(); ++i) {
ShenandoahHeapRegion* r = heap->get_region(i);
if (r->is_young()) {
young_region_ages.add(r->age(), r->get_live_data_words());
if (heap->mode()->is_generational()) {
AgeTable young_region_ages(false);
for (uint i = 0; i < heap->num_regions(); ++i) {
ShenandoahHeapRegion* r = heap->get_region(i);
if (r->is_young()) {
young_region_ages.add(r->age(), r->get_live_data_words());
}
}
st->print("Young regions: ");
young_region_ages.print_on(st);
st->cr();
}
st->print("Young regions: ");
young_region_ages.print_on(st);
st->cr();
}
class ShenandoahStatAggregator : public ThreadClosure {

View File

@ -324,8 +324,11 @@ oop ShenandoahGenerationalHeap::try_evacuate_object(oop p, Thread* thread, Shena
return ShenandoahBarrierSet::resolve_forwarded(p);
}
if (ShenandoahEvacTracking) {
evac_tracker()->begin_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen);
}
// Copy the object:
NOT_PRODUCT(evac_tracker()->begin_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen));
Copy::aligned_disjoint_words(cast_from_oop<HeapWord*>(p), copy, size);
oop copy_val = cast_to_oop(copy);
@ -346,8 +349,10 @@ oop ShenandoahGenerationalHeap::try_evacuate_object(oop p, Thread* thread, Shena
// safe to do this on the public copy (this is also done during concurrent mark).
ContinuationGCSupport::relativize_stack_chunk(copy_val);
// Record that the evacuation succeeded
NOT_PRODUCT(evac_tracker()->end_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen));
if (ShenandoahEvacTracking) {
// Record that the evacuation succeeded
evac_tracker()->end_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen);
}
if (target_gen == OLD_GENERATION) {
old_generation()->handle_evacuation(copy, size, from_region->is_young());

View File

@ -1371,8 +1371,11 @@ oop ShenandoahHeap::try_evacuate_object(oop p, Thread* thread, ShenandoahHeapReg
return ShenandoahBarrierSet::resolve_forwarded(p);
}
if (ShenandoahEvacTracking) {
evac_tracker()->begin_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen);
}
// Copy the object:
NOT_PRODUCT(evac_tracker()->begin_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen));
Copy::aligned_disjoint_words(cast_from_oop<HeapWord*>(p), copy, size);
// Try to install the new forwarding pointer.
@ -1382,7 +1385,9 @@ oop ShenandoahHeap::try_evacuate_object(oop p, Thread* thread, ShenandoahHeapReg
// Successfully evacuated. Our copy is now the public one!
ContinuationGCSupport::relativize_stack_chunk(copy_val);
shenandoah_assert_correct(nullptr, copy_val);
NOT_PRODUCT(evac_tracker()->end_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen));
if (ShenandoahEvacTracking) {
evac_tracker()->end_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen);
}
return copy_val;
} else {
// Failed to evacuate. We need to deal with the object that is left behind. Since this
@ -1612,12 +1617,11 @@ void ShenandoahHeap::print_tracing_info() const {
ResourceMark rm;
LogStream ls(lt);
#ifdef NOT_PRODUCT
evac_tracker()->print_global_on(&ls);
ls.cr();
ls.cr();
#endif
if (ShenandoahEvacTracking) {
evac_tracker()->print_global_on(&ls);
ls.cr();
ls.cr();
}
phase_timings()->print_global_on(&ls);

View File

@ -408,6 +408,13 @@
"events.") \
range(0,100) \
\
product(bool, ShenandoahEvacTracking, false, DIAGNOSTIC, \
"Collect additional metrics about evacuations. Enabling this " \
"tracks how many objects and how many bytes were evacuated, and " \
"how many were abandoned. The information will be categorized " \
"by thread type (worker or mutator) and evacuation type (young, " \
"old, or promotion.") \
\
product(uintx, ShenandoahMinYoungPercentage, 20, EXPERIMENTAL, \
"The minimum percentage of the heap to use for the young " \
"generation. Heuristics will not adjust the young generation " \