mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-28 03:43:21 +00:00
8368499: GenShen: Do not collect age census during evac when adaptive tenuring is disabled
Reviewed-by: kdnilsen, ysr
This commit is contained in:
parent
569e78080b
commit
8ca1feaf7e
@ -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();
|
||||
|
||||
|
||||
@ -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<mtGC> {
|
||||
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<mtGC> {
|
||||
// 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<mtGC> {
|
||||
// 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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user