From 8ca1feaf7e29c1370853b9b95c2ee7a62c6b84b7 Mon Sep 17 00:00:00 2001 From: William Kemper Date: Thu, 25 Sep 2025 15:37:02 +0000 Subject: [PATCH] 8368499: GenShen: Do not collect age census during evac when adaptive tenuring is disabled Reviewed-by: kdnilsen, ysr --- .../gc/shenandoah/shenandoahAgeCensus.cpp | 100 +++++++++--------- .../gc/shenandoah/shenandoahAgeCensus.hpp | 12 +-- .../gc/shenandoah/shenandoahControlThread.cpp | 22 +--- .../gc/shenandoah/shenandoahEvacTracker.cpp | 75 ++----------- .../gc/shenandoah/shenandoahEvacTracker.hpp | 9 -- .../shenandoahGenerationalControlThread.cpp | 49 +++++---- .../shenandoahGenerationalControlThread.hpp | 6 +- .../shenandoah/shenandoahGenerationalHeap.cpp | 5 - .../share/gc/shenandoah/shenandoahHeap.cpp | 21 ++++ .../share/gc/shenandoah/shenandoahHeap.hpp | 5 +- .../shenandoah/shenandoahThreadLocalData.hpp | 4 - 11 files changed, 113 insertions(+), 195 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp b/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp index c3b99af8a80..86ff6f22c72 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.cpp @@ -43,7 +43,7 @@ ShenandoahAgeCensus::ShenandoahAgeCensus(uint max_workers) ShenandoahGenerationalMinTenuringAge, ShenandoahGenerationalMaxTenuringAge)); } - _global_age_table = NEW_C_HEAP_ARRAY(AgeTable*, MAX_SNAPSHOTS, mtGC); + _global_age_tables = NEW_C_HEAP_ARRAY(AgeTable*, MAX_SNAPSHOTS, mtGC); CENSUS_NOISE(_global_noise = NEW_C_HEAP_ARRAY(ShenandoahNoiseStats, MAX_SNAPSHOTS, mtGC);) _tenuring_threshold = NEW_C_HEAP_ARRAY(uint, MAX_SNAPSHOTS, mtGC); CENSUS_NOISE(_skipped = 0); @@ -52,36 +52,40 @@ ShenandoahAgeCensus::ShenandoahAgeCensus(uint max_workers) for (int i = 0; i < MAX_SNAPSHOTS; i++) { // Note that we don't now get perfdata from age_table - _global_age_table[i] = new AgeTable(false); + _global_age_tables[i] = new AgeTable(false); CENSUS_NOISE(_global_noise[i].clear();) // Sentinel value _tenuring_threshold[i] = MAX_COHORTS; } if (ShenandoahGenerationalAdaptiveTenuring) { - _local_age_table = NEW_C_HEAP_ARRAY(AgeTable*, _max_workers, mtGC); + _local_age_tables = NEW_C_HEAP_ARRAY(AgeTable*, _max_workers, mtGC); CENSUS_NOISE(_local_noise = NEW_C_HEAP_ARRAY(ShenandoahNoiseStats, max_workers, mtGC);) for (uint i = 0; i < _max_workers; i++) { - _local_age_table[i] = new AgeTable(false); + _local_age_tables[i] = new AgeTable(false); CENSUS_NOISE(_local_noise[i].clear();) } } else { - _local_age_table = nullptr; + _local_age_tables = nullptr; + } + _epoch = MAX_SNAPSHOTS - 1; // see prepare_for_census_update() + + if (!ShenandoahGenerationalAdaptiveTenuring) { + _tenuring_threshold[_epoch] = InitialTenuringThreshold; } - _epoch = MAX_SNAPSHOTS - 1; // see update_epoch() } ShenandoahAgeCensus::~ShenandoahAgeCensus() { for (uint i = 0; i < MAX_SNAPSHOTS; i++) { - delete _global_age_table[i]; + delete _global_age_tables[i]; } - FREE_C_HEAP_ARRAY(AgeTable*, _global_age_table); + FREE_C_HEAP_ARRAY(AgeTable*, _global_age_tables); FREE_C_HEAP_ARRAY(uint, _tenuring_threshold); CENSUS_NOISE(FREE_C_HEAP_ARRAY(ShenandoahNoiseStats, _global_noise)); - if (_local_age_table) { + if (_local_age_tables) { for (uint i = 0; i < _max_workers; i++) { - delete _local_age_table[i]; + delete _local_age_tables[i]; } - FREE_C_HEAP_ARRAY(AgeTable*, _local_age_table); + FREE_C_HEAP_ARRAY(AgeTable*, _local_age_tables); CENSUS_NOISE(FREE_C_HEAP_ARRAY(ShenandoahNoiseStats, _local_noise)); } } @@ -142,37 +146,31 @@ void ShenandoahAgeCensus::prepare_for_census_update() { if (++_epoch >= MAX_SNAPSHOTS) { _epoch=0; } - _global_age_table[_epoch]->clear(); + _global_age_tables[_epoch]->clear(); CENSUS_NOISE(_global_noise[_epoch].clear();) } // Update the census data from appropriate sources, // and compute the new tenuring threshold. -void ShenandoahAgeCensus::update_census(size_t age0_pop, AgeTable* pv1, AgeTable* pv2) { +void ShenandoahAgeCensus::update_census(size_t age0_pop) { prepare_for_census_update(); - assert(_global_age_table[_epoch]->is_clear(), "Dirty decks"); + assert(ShenandoahGenerationalAdaptiveTenuring, "Only update census when adaptive tenuring is enabled"); + assert(_global_age_tables[_epoch]->is_clear(), "Dirty decks"); CENSUS_NOISE(assert(_global_noise[_epoch].is_clear(), "Dirty decks");) - if (ShenandoahGenerationalAdaptiveTenuring) { - assert(pv1 == nullptr && pv2 == nullptr, "Error, check caller"); - // Seed cohort 0 with population that may have been missed during - // regular census. - _global_age_table[_epoch]->add(0u, age0_pop); - // Merge data from local age tables into the global age table for the epoch, - // clearing the local tables. - for (uint i = 0; i < _max_workers; i++) { - // age stats - _global_age_table[_epoch]->merge(_local_age_table[i]); - _local_age_table[i]->clear(); // clear for next census - // Merge noise stats - CENSUS_NOISE(_global_noise[_epoch].merge(_local_noise[i]);) - CENSUS_NOISE(_local_noise[i].clear();) - } - } else { - // census during evac - assert(pv1 != nullptr && pv2 != nullptr, "Error, check caller"); - _global_age_table[_epoch]->merge(pv1); - _global_age_table[_epoch]->merge(pv2); + // Seed cohort 0 with population that may have been missed during + // regular census. + _global_age_tables[_epoch]->add(0u, age0_pop); + + // Merge data from local age tables into the global age table for the epoch, + // clearing the local tables. + for (uint i = 0; i < _max_workers; i++) { + // age stats + _global_age_tables[_epoch]->merge(_local_age_tables[i]); + _local_age_tables[i]->clear(); // clear for next census + // Merge noise stats + CENSUS_NOISE(_global_noise[_epoch].merge(_local_noise[i]);) + CENSUS_NOISE(_local_noise[i].clear();) } update_tenuring_threshold(); @@ -188,7 +186,7 @@ void ShenandoahAgeCensus::update_census(size_t age0_pop, AgeTable* pv1, AgeTable void ShenandoahAgeCensus::reset_global() { assert(_epoch < MAX_SNAPSHOTS, "Out of bounds"); for (uint i = 0; i < MAX_SNAPSHOTS; i++) { - _global_age_table[i]->clear(); + _global_age_tables[i]->clear(); CENSUS_NOISE(_global_noise[i].clear();) } _epoch = MAX_SNAPSHOTS; @@ -198,11 +196,11 @@ void ShenandoahAgeCensus::reset_global() { // Reset the local age tables, clearing any partial census. void ShenandoahAgeCensus::reset_local() { if (!ShenandoahGenerationalAdaptiveTenuring) { - assert(_local_age_table == nullptr, "Error"); + assert(_local_age_tables == nullptr, "Error"); return; } for (uint i = 0; i < _max_workers; i++) { - _local_age_table[i]->clear(); + _local_age_tables[i]->clear(); CENSUS_NOISE(_local_noise[i].clear();) } } @@ -212,7 +210,7 @@ void ShenandoahAgeCensus::reset_local() { bool ShenandoahAgeCensus::is_clear_global() { assert(_epoch < MAX_SNAPSHOTS, "Out of bounds"); for (uint i = 0; i < MAX_SNAPSHOTS; i++) { - bool clear = _global_age_table[i]->is_clear(); + bool clear = _global_age_tables[i]->is_clear(); CENSUS_NOISE(clear |= _global_noise[i].is_clear();) if (!clear) { return false; @@ -224,11 +222,11 @@ bool ShenandoahAgeCensus::is_clear_global() { // Is local census information clear? bool ShenandoahAgeCensus::is_clear_local() { if (!ShenandoahGenerationalAdaptiveTenuring) { - assert(_local_age_table == nullptr, "Error"); + assert(_local_age_tables == nullptr, "Error"); return true; } for (uint i = 0; i < _max_workers; i++) { - bool clear = _local_age_table[i]->is_clear(); + bool clear = _local_age_tables[i]->is_clear(); CENSUS_NOISE(clear |= _local_noise[i].is_clear();) if (!clear) { return false; @@ -240,7 +238,7 @@ bool ShenandoahAgeCensus::is_clear_local() { size_t ShenandoahAgeCensus::get_all_ages(uint snap) { assert(snap < MAX_SNAPSHOTS, "Out of bounds"); size_t pop = 0; - const AgeTable* pv = _global_age_table[snap]; + const AgeTable* pv = _global_age_tables[snap]; for (uint i = 0; i < MAX_COHORTS; i++) { pop += pv->sizes[i]; } @@ -260,13 +258,11 @@ void ShenandoahAgeCensus::update_total() { #endif // !PRODUCT void ShenandoahAgeCensus::update_tenuring_threshold() { - if (!ShenandoahGenerationalAdaptiveTenuring) { - _tenuring_threshold[_epoch] = InitialTenuringThreshold; - } else { - uint tt = compute_tenuring_threshold(); - assert(tt <= MAX_COHORTS, "Out of bounds"); - _tenuring_threshold[_epoch] = tt; - } + assert(ShenandoahGenerationalAdaptiveTenuring, "Only update when adaptive tenuring is enabled"); + uint tt = compute_tenuring_threshold(); + assert(tt <= MAX_COHORTS, "Out of bounds"); + _tenuring_threshold[_epoch] = tt; + print(); log_info(gc, age)("New tenuring threshold %zu (min %zu, max %zu)", (uintx) _tenuring_threshold[_epoch], ShenandoahGenerationalMinTenuringAge, ShenandoahGenerationalMaxTenuringAge); @@ -296,8 +292,8 @@ uint ShenandoahAgeCensus::compute_tenuring_threshold() { const uint prev_epoch = cur_epoch > 0 ? cur_epoch - 1 : markWord::max_age; // Current and previous population vectors in ring - const AgeTable* cur_pv = _global_age_table[cur_epoch]; - const AgeTable* prev_pv = _global_age_table[prev_epoch]; + const AgeTable* cur_pv = _global_age_tables[cur_epoch]; + const AgeTable* prev_pv = _global_age_tables[prev_epoch]; uint upper_bound = ShenandoahGenerationalMaxTenuringAge; const uint prev_tt = previous_tenuring_threshold(); if (ShenandoahGenerationalCensusIgnoreOlderCohorts && prev_tt > 0) { @@ -372,8 +368,8 @@ void ShenandoahAgeCensus::print() { const uint cur_epoch = _epoch; const uint prev_epoch = cur_epoch > 0 ? cur_epoch - 1: markWord::max_age; - const AgeTable* cur_pv = _global_age_table[cur_epoch]; - const AgeTable* prev_pv = _global_age_table[prev_epoch]; + const AgeTable* cur_pv = _global_age_tables[cur_epoch]; + const AgeTable* prev_pv = _global_age_tables[prev_epoch]; const uint tt = tenuring_threshold(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.hpp b/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.hpp index d862498c69d..39ea4ee9002 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAgeCensus.hpp @@ -97,8 +97,8 @@ struct ShenandoahNoiseStats { // once the per-worker data is consolidated into the appropriate population vector // per minor collection. The _local_age_table is thus C x N, for N GC workers. class ShenandoahAgeCensus: public CHeapObj { - AgeTable** _global_age_table; // Global age table used for adapting tenuring threshold, one per snapshot - AgeTable** _local_age_table; // Local scratch age tables to track object ages, one per worker + AgeTable** _global_age_tables; // Global age tables used for adapting tenuring threshold, one per snapshot + AgeTable** _local_age_tables; // Local scratch age tables to track object ages, one per worker #ifdef SHENANDOAH_CENSUS_NOISE ShenandoahNoiseStats* _global_noise; // Noise stats, one per snapshot @@ -175,7 +175,7 @@ class ShenandoahAgeCensus: public CHeapObj { // Return the local age table (population vector) for worker_id. // Only used in the case of ShenandoahGenerationalAdaptiveTenuring AgeTable* get_local_age_table(uint worker_id) const { - return _local_age_table[worker_id]; + return _local_age_tables[worker_id]; } // Return the most recently computed tenuring threshold. @@ -209,11 +209,7 @@ class ShenandoahAgeCensus: public CHeapObj { // age0_pop is the population of Cohort 0 that may have been missed in // the regular census during the marking cycle, corresponding to objects // allocated when the concurrent marking was in progress. - // Optional parameters, pv1 and pv2 are population vectors that together - // provide object census data (only) for the case when - // ShenandoahGenerationalCensusAtEvac. In this case, the age0_pop - // is 0, because the evacuated objects have all had their ages incremented. - void update_census(size_t age0_pop, AgeTable* pv1 = nullptr, AgeTable* pv2 = nullptr); + void update_census(size_t age0_pop); // Reset the epoch, clearing accumulated census history // Note: this isn't currently used, but reserved for planned diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp index f4005e45f39..b960255891f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp @@ -201,26 +201,8 @@ void ShenandoahControlThread::run_service() { heuristics->clear_metaspace_oom(); } - // Commit worker statistics to cycle data - heap->phase_timings()->flush_par_workers_to_cycle(); - - // Print GC stats for current cycle - { - LogTarget(Info, gc, stats) lt; - if (lt.is_enabled()) { - ResourceMark rm; - LogStream ls(lt); - heap->phase_timings()->print_cycle_on(&ls); - 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); - } - } - } - - // Commit statistics to globals - heap->phase_timings()->flush_cycle_to_global(); + // Manage and print gc stats + heap->process_gc_stats(); // Print Metaspace change following GC (if logging is enabled). MetaspaceUtils::print_metaspace_change(meta_sizes); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp b/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp index bc8fad713af..72d0773eccd 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.cpp @@ -23,7 +23,6 @@ * */ -#include "gc/shenandoah/shenandoahAgeCensus.hpp" #include "gc/shenandoah/shenandoahEvacTracker.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahThreadLocalData.hpp" @@ -44,19 +43,6 @@ ShenandoahEvacuationStats::ShenandoahEvacuations* ShenandoahEvacuationStats::get return &_old; } -ShenandoahEvacuationStats::ShenandoahEvacuationStats() - : _use_age_table(!ShenandoahGenerationalAdaptiveTenuring), - _age_table(nullptr) { - if (_use_age_table) { - _age_table = new AgeTable(false); - } -} - -AgeTable* ShenandoahEvacuationStats::age_table() const { - assert(_use_age_table, "Don't call"); - return _age_table; -} - void ShenandoahEvacuationStats::begin_evacuation(size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to) { ShenandoahEvacuations* category = get_category(from, to); category->_evacuations_attempted++; @@ -70,31 +56,16 @@ void ShenandoahEvacuationStats::end_evacuation(size_t bytes, ShenandoahAffiliati category->_bytes_completed += bytes; } -void ShenandoahEvacuationStats::record_age(size_t bytes, uint age) { - assert(_use_age_table, "Don't call!"); - if (age <= markWord::max_age) { // Filter age sentinel. - _age_table->add(age, bytes >> LogBytesPerWord); - } -} - void ShenandoahEvacuationStats::accumulate(const ShenandoahEvacuationStats* other) { _young.accumulate(other->_young); _old.accumulate(other->_old); _promotion.accumulate(other->_promotion); - - if (_use_age_table) { - _age_table->merge(other->age_table()); - } } void ShenandoahEvacuationStats::reset() { _young.reset(); _old.reset(); _promotion.reset(); - - if (_use_age_table) { - _age_table->clear(); - } } void ShenandoahEvacuationStats::ShenandoahEvacuations::print_on(outputStream* st) const { @@ -112,10 +83,6 @@ void ShenandoahEvacuationStats::print_on(outputStream* st) const { st->print("Promotion: "); _promotion.print_on(st); st->print("Old: "); _old.print_on(st); } - - if (_use_age_table) { - _age_table->print_on(st); - } } void ShenandoahEvacuationTracker::print_global_on(outputStream* st) { @@ -125,28 +92,13 @@ void ShenandoahEvacuationTracker::print_global_on(outputStream* st) { void ShenandoahEvacuationTracker::print_evacuations_on(outputStream* st, ShenandoahEvacuationStats* workers, ShenandoahEvacuationStats* mutators) { - 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(); - 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(); - } + assert(ShenandoahEvacTracking, "Only when evac tracking is enabled"); + st->print_cr("Workers: "); + workers->print_on(st); + st->cr(); + st->print_cr("Mutators: "); + mutators->print_on(st); + st->cr(); } class ShenandoahStatAggregator : public ThreadClosure { @@ -173,15 +125,6 @@ ShenandoahCycleStats ShenandoahEvacuationTracker::flush_cycle_to_global() { _mutators_global.accumulate(&mutators); _workers_global.accumulate(&workers); - if (!ShenandoahGenerationalAdaptiveTenuring) { - // Ingest mutator & worker collected population vectors into the heap's - // global census data, and use it to compute an appropriate tenuring threshold - // for use in the next cycle. - // The first argument is used for any age 0 cohort population that we may otherwise have - // missed during the census. This is non-zero only when census happens at marking. - ShenandoahGenerationalHeap::heap()->age_census()->update_census(0, mutators.age_table(), workers.age_table()); - } - return {workers, mutators}; } @@ -192,7 +135,3 @@ void ShenandoahEvacuationTracker::begin_evacuation(Thread* thread, size_t bytes, void ShenandoahEvacuationTracker::end_evacuation(Thread* thread, size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to) { ShenandoahThreadLocalData::end_evacuation(thread, bytes, from, to); } - -void ShenandoahEvacuationTracker::record_age(Thread* thread, size_t bytes, uint age) { - ShenandoahThreadLocalData::record_age(thread, bytes, age); -} diff --git a/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.hpp b/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.hpp index e5d7a7fec94..6e1182680a5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahEvacTracker.hpp @@ -66,20 +66,12 @@ private: ShenandoahEvacuations _old; ShenandoahEvacuations _promotion; - bool _use_age_table; - AgeTable* _age_table; - public: - ShenandoahEvacuationStats(); - - AgeTable* age_table() const; - // Record that the current thread is attempting to copy this many bytes. void begin_evacuation(size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to); // Record that the current thread has completed copying this many bytes. void end_evacuation(size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to); - void record_age(size_t bytes, uint age); void print_on(outputStream* st) const; void accumulate(const ShenandoahEvacuationStats* other); @@ -106,7 +98,6 @@ public: // Multiple threads may attempt to evacuate the same object, but only the successful thread will end the evacuation. // Evacuations that were begun, but not ended are considered 'abandoned'. void end_evacuation(Thread* thread, size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to); - void record_age(Thread* thread, size_t bytes, uint age); void print_global_on(outputStream* st); void print_evacuations_on(outputStream* st, diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp index 761ba02d569..c6d1cf02ee2 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp @@ -201,6 +201,24 @@ ShenandoahGenerationalControlThread::GCMode ShenandoahGenerationalControlThread: return request.generation->is_old() ? servicing_old : concurrent_normal; } +void ShenandoahGenerationalControlThread::maybe_print_young_region_ages() const { + LogTarget(Debug, gc, age) lt; + if (lt.is_enabled()) { + LogStream ls(lt); + AgeTable young_region_ages(false); + for (uint i = 0; i < _heap->num_regions(); ++i) { + const ShenandoahHeapRegion* r = _heap->get_region(i); + if (r->is_young()) { + young_region_ages.add(r->age(), r->get_live_data_words()); + } + } + + ls.print("Young regions: "); + young_region_ages.print_on(&ls); + ls.cr(); + } +} + void ShenandoahGenerationalControlThread::maybe_set_aging_cycle() { if (_age_period-- == 0) { _heap->set_aging_cycle(true); @@ -298,7 +316,11 @@ void ShenandoahGenerationalControlThread::run_gc_cycle(const ShenandoahGCRequest _heap->global_generation()->heuristics()->clear_metaspace_oom(); } - process_phase_timings(); + // Manage and print gc stats + _heap->process_gc_stats(); + + // Print table for young region ages if log is enabled + maybe_print_young_region_ages(); // Print Metaspace change following GC (if logging is enabled). MetaspaceUtils::print_metaspace_change(meta_sizes); @@ -317,29 +339,6 @@ void ShenandoahGenerationalControlThread::run_gc_cycle(const ShenandoahGCRequest gc_mode_name(gc_mode()), GCCause::to_string(request.cause), request.generation->name(), GCCause::to_string(_heap->cancelled_cause())); } -void ShenandoahGenerationalControlThread::process_phase_timings() const { - // Commit worker statistics to cycle data - _heap->phase_timings()->flush_par_workers_to_cycle(); - - ShenandoahEvacuationTracker* evac_tracker = _heap->evac_tracker(); - ShenandoahCycleStats evac_stats = evac_tracker->flush_cycle_to_global(); - - // Print GC stats for current cycle - { - LogTarget(Info, gc, stats) lt; - if (lt.is_enabled()) { - ResourceMark rm; - LogStream ls(lt); - _heap->phase_timings()->print_cycle_on(&ls); - evac_tracker->print_evacuations_on(&ls, &evac_stats.workers, - &evac_stats.mutators); - } - } - - // Commit statistics to globals - _heap->phase_timings()->flush_cycle_to_global(); -} - // Young and old concurrent cycles are initiated by the regulator. Implicit // and explicit GC requests are handled by the controller thread and always // run a global cycle (which is concurrent by default, but may be overridden @@ -417,7 +416,7 @@ void ShenandoahGenerationalControlThread::service_concurrent_old_cycle(const She set_gc_mode(bootstrapping_old); young_generation->set_old_gen_task_queues(old_generation->task_queues()); service_concurrent_cycle(young_generation, request.cause, true); - process_phase_timings(); + _heap->process_gc_stats(); if (_heap->cancelled_gc()) { // Young generation bootstrap cycle has failed. Concurrent mark for old generation // is going to resume after degenerated bootstrap cycle completes. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp index 1586205742a..6a4f5bde578 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp @@ -129,9 +129,6 @@ private: // Returns true if the old generation marking was interrupted to allow a young cycle. bool preempt_old_marking(ShenandoahGeneration* generation); - // Flushes cycle timings to global timings and prints the phase timings for the last completed cycle. - void process_phase_timings() const; - // Set the gc mode and post a notification if it has changed. The overloaded variant should be used // when the _control_lock is already held. void set_gc_mode(GCMode new_mode); @@ -160,6 +157,9 @@ private: GCMode prepare_for_allocation_failure_gc(ShenandoahGCRequest &request); GCMode prepare_for_explicit_gc(ShenandoahGCRequest &request) const; GCMode prepare_for_concurrent_gc(const ShenandoahGCRequest &request) const; + + // Print table for young region ages if log is enabled + void maybe_print_young_region_ages() const; }; #endif // SHARE_GC_SHENANDOAH_SHENANDOAHGENERATIONALCONTROLTHREAD_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp index 8a21ae376e1..34f217ada25 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp @@ -360,11 +360,6 @@ oop ShenandoahGenerationalHeap::try_evacuate_object(oop p, Thread* thread, Shena // When copying to the old generation above, we don't care // about recording object age in the census stats. assert(target_gen == YOUNG_GENERATION, "Error"); - // We record this census only when simulating pre-adaptive tenuring behavior, or - // when we have been asked to record the census at evacuation rather than at mark - if (!ShenandoahGenerationalAdaptiveTenuring) { - evac_tracker()->record_age(thread, size * HeapWordSize, ShenandoahHeap::get_object_age(copy_val)); - } } shenandoah_assert_correct(nullptr, copy_val); return copy_val; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index 10d7e8edcad..e6d41237c98 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -1441,6 +1441,27 @@ void ShenandoahHeap::print_heap_regions_on(outputStream* st) const { } } +void ShenandoahHeap::process_gc_stats() const { + // Commit worker statistics to cycle data + phase_timings()->flush_par_workers_to_cycle(); + + // Print GC stats for current cycle + LogTarget(Info, gc, stats) lt; + if (lt.is_enabled()) { + ResourceMark rm; + LogStream ls(lt); + phase_timings()->print_cycle_on(&ls); + if (ShenandoahEvacTracking) { + ShenandoahCycleStats evac_stats = evac_tracker()->flush_cycle_to_global(); + evac_tracker()->print_evacuations_on(&ls, &evac_stats.workers, + &evac_stats.mutators); + } + } + + // Commit statistics to globals + phase_timings()->flush_cycle_to_global(); +} + size_t ShenandoahHeap::trash_humongous_region_at(ShenandoahHeapRegion* start) const { assert(start->is_humongous_start(), "reclaim regions starting with the first one"); assert(!start->has_live(), "liveness must be zero"); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index 322ac26e254..11a20d4a2f9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -206,9 +206,12 @@ public: void initialize_serviceability() override; void print_heap_on(outputStream* st) const override; - void print_gc_on(outputStream *st) const override; + void print_gc_on(outputStream* st) const override; void print_heap_regions_on(outputStream* st) const; + // Flushes cycle timings to global timings and prints the phase timings for the last completed cycle. + void process_gc_stats() const; + void prepare_for_verify() override; void verify(VerifyOption vo) override; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp b/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp index 37d935d1f78..f54a65b0785 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahThreadLocalData.hpp @@ -166,10 +166,6 @@ public: data(thread)->_evacuation_stats->end_evacuation(bytes, from, to); } - static void record_age(Thread* thread, size_t bytes, uint age) { - data(thread)->_evacuation_stats->record_age(bytes, age); - } - static ShenandoahEvacuationStats* evacuation_stats(Thread* thread) { return data(thread)->_evacuation_stats; }