Skip to content

Commit e756c0d

Browse files
author
William Kemper
committed
8361726: Shenandoah: More detailed evacuation instrumentation
Reviewed-by: ysr, kdnilsen
1 parent 89fe586 commit e756c0d

9 files changed

+130
-70
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,12 @@ void ShenandoahControlThread::run_service() {
210210
ResourceMark rm;
211211
LogStream ls(lt);
212212
heap->phase_timings()->print_cycle_on(&ls);
213+
#ifdef NOT_PRODUCT
214+
ShenandoahEvacuationTracker* evac_tracker = heap->evac_tracker();
215+
ShenandoahCycleStats evac_stats = evac_tracker->flush_cycle_to_global();
216+
evac_tracker->print_evacuations_on(&ls, &evac_stats.workers,
217+
&evac_stats.mutators);
218+
#endif
213219
}
214220
}
215221

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

Lines changed: 50 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,22 @@
3030
#include "runtime/thread.hpp"
3131
#include "runtime/threadSMR.inline.hpp"
3232

33+
ShenandoahEvacuationStats::ShenandoahEvacuations* ShenandoahEvacuationStats::get_category(
34+
ShenandoahAffiliation from,
35+
ShenandoahAffiliation to) {
36+
if (from == YOUNG_GENERATION) {
37+
if (to == YOUNG_GENERATION) {
38+
return &_young;
39+
}
40+
assert(to == OLD_GENERATION, "If not evacuating to young, must be promotion to old");
41+
return &_promotion;
42+
}
43+
assert(from == OLD_GENERATION, "If not evacuating from young, then must be from old");
44+
return &_old;
45+
}
46+
3347
ShenandoahEvacuationStats::ShenandoahEvacuationStats()
34-
: _evacuations_completed(0), _bytes_completed(0),
35-
_evacuations_attempted(0), _bytes_attempted(0),
36-
_use_age_table(ShenandoahGenerationalCensusAtEvac || !ShenandoahGenerationalAdaptiveTenuring),
48+
: _use_age_table(ShenandoahGenerationalCensusAtEvac || !ShenandoahGenerationalAdaptiveTenuring),
3749
_age_table(nullptr) {
3850
if (_use_age_table) {
3951
_age_table = new AgeTable(false);
@@ -45,14 +57,17 @@ AgeTable* ShenandoahEvacuationStats::age_table() const {
4557
return _age_table;
4658
}
4759

48-
void ShenandoahEvacuationStats::begin_evacuation(size_t bytes) {
49-
++_evacuations_attempted;
50-
_bytes_attempted += bytes;
60+
void ShenandoahEvacuationStats::begin_evacuation(size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to) {
61+
ShenandoahEvacuations* category = get_category(from, to);
62+
category->_evacuations_attempted++;
63+
category->_bytes_attempted += bytes;
64+
5165
}
5266

53-
void ShenandoahEvacuationStats::end_evacuation(size_t bytes) {
54-
++_evacuations_completed;
55-
_bytes_completed += bytes;
67+
void ShenandoahEvacuationStats::end_evacuation(size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to) {
68+
ShenandoahEvacuations* category = get_category(from, to);
69+
category->_evacuations_completed++;
70+
category->_bytes_completed += bytes;
5671
}
5772

5873
void ShenandoahEvacuationStats::record_age(size_t bytes, uint age) {
@@ -63,34 +78,39 @@ void ShenandoahEvacuationStats::record_age(size_t bytes, uint age) {
6378
}
6479

6580
void ShenandoahEvacuationStats::accumulate(const ShenandoahEvacuationStats* other) {
66-
_evacuations_completed += other->_evacuations_completed;
67-
_bytes_completed += other->_bytes_completed;
68-
_evacuations_attempted += other->_evacuations_attempted;
69-
_bytes_attempted += other->_bytes_attempted;
81+
_young.accumulate(other->_young);
82+
_old.accumulate(other->_old);
83+
_promotion.accumulate(other->_promotion);
84+
7085
if (_use_age_table) {
7186
_age_table->merge(other->age_table());
7287
}
7388
}
7489

7590
void ShenandoahEvacuationStats::reset() {
76-
_evacuations_completed = _evacuations_attempted = 0;
77-
_bytes_completed = _bytes_attempted = 0;
91+
_young.reset();
92+
_old.reset();
93+
_promotion.reset();
94+
7895
if (_use_age_table) {
7996
_age_table->clear();
8097
}
8198
}
8299

83-
void ShenandoahEvacuationStats::print_on(outputStream* st) {
84-
#ifndef PRODUCT
100+
void ShenandoahEvacuationStats::ShenandoahEvacuations::print_on(outputStream* st) const {
85101
size_t abandoned_size = _bytes_attempted - _bytes_completed;
86102
size_t abandoned_count = _evacuations_attempted - _evacuations_completed;
87-
st->print_cr("Evacuated %zu%s across %zu objects, "
88-
"abandoned %zu%s across %zu objects.",
89-
byte_size_in_proper_unit(_bytes_completed), proper_unit_for_byte_size(_bytes_completed),
90-
_evacuations_completed,
91-
byte_size_in_proper_unit(abandoned_size), proper_unit_for_byte_size(abandoned_size),
92-
abandoned_count);
93-
#endif
103+
st->print_cr("Evacuated " PROPERFMT" across %zu objects, "
104+
"abandoned " PROPERFMT " across %zu objects.",
105+
PROPERFMTARGS(_bytes_completed), _evacuations_completed,
106+
PROPERFMTARGS(abandoned_size), abandoned_count);
107+
}
108+
109+
void ShenandoahEvacuationStats::print_on(outputStream* st) const {
110+
st->print("Young: "); _young.print_on(st);
111+
st->print("Promotion: "); _promotion.print_on(st);
112+
st->print("Old: "); _old.print_on(st);
113+
94114
if (_use_age_table) {
95115
_age_table->print_on(st);
96116
}
@@ -103,10 +123,10 @@ void ShenandoahEvacuationTracker::print_global_on(outputStream* st) {
103123
void ShenandoahEvacuationTracker::print_evacuations_on(outputStream* st,
104124
ShenandoahEvacuationStats* workers,
105125
ShenandoahEvacuationStats* mutators) {
106-
st->print("Workers: ");
126+
st->print_cr("Workers: ");
107127
workers->print_on(st);
108128
st->cr();
109-
st->print("Mutators: ");
129+
st->print_cr("Mutators: ");
110130
mutators->print_on(st);
111131
st->cr();
112132

@@ -160,12 +180,12 @@ ShenandoahCycleStats ShenandoahEvacuationTracker::flush_cycle_to_global() {
160180
return {workers, mutators};
161181
}
162182

163-
void ShenandoahEvacuationTracker::begin_evacuation(Thread* thread, size_t bytes) {
164-
ShenandoahThreadLocalData::begin_evacuation(thread, bytes);
183+
void ShenandoahEvacuationTracker::begin_evacuation(Thread* thread, size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to) {
184+
ShenandoahThreadLocalData::begin_evacuation(thread, bytes, from, to);
165185
}
166186

167-
void ShenandoahEvacuationTracker::end_evacuation(Thread* thread, size_t bytes) {
168-
ShenandoahThreadLocalData::end_evacuation(thread, bytes);
187+
void ShenandoahEvacuationTracker::end_evacuation(Thread* thread, size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to) {
188+
ShenandoahThreadLocalData::end_evacuation(thread, bytes, from, to);
169189
}
170190

171191
void ShenandoahEvacuationTracker::record_age(Thread* thread, size_t bytes, uint age) {

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

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,45 @@
2626
#define SHARE_GC_SHENANDOAH_SHENANDOAHEVACTRACKER_HPP
2727

2828
#include "gc/shared/ageTable.hpp"
29+
#include "gc/shenandoah/shenandoahAffiliation.hpp"
2930
#include "utilities/ostream.hpp"
3031

3132
class ShenandoahEvacuationStats : public CHeapObj<mtGC> {
3233
private:
33-
size_t _evacuations_completed;
34-
size_t _bytes_completed;
35-
size_t _evacuations_attempted;
36-
size_t _bytes_attempted;
34+
struct ShenandoahEvacuations {
35+
size_t _evacuations_completed;
36+
size_t _bytes_completed;
37+
size_t _evacuations_attempted;
38+
size_t _bytes_attempted;
39+
ShenandoahEvacuations()
40+
: _evacuations_completed(0)
41+
, _bytes_completed(0)
42+
, _evacuations_attempted(0)
43+
, _bytes_attempted(0) {
44+
}
45+
46+
void accumulate(const ShenandoahEvacuations& other) {
47+
_evacuations_completed += other._evacuations_completed;
48+
_bytes_completed += other._bytes_completed;
49+
_evacuations_attempted += other._evacuations_attempted;
50+
_bytes_attempted += other._bytes_attempted;
51+
}
52+
53+
void reset() {
54+
_evacuations_completed = 0;
55+
_bytes_completed = 0;
56+
_evacuations_attempted = 0;
57+
_bytes_attempted = 0;
58+
}
59+
60+
void print_on(outputStream* st) const;
61+
};
62+
63+
ShenandoahEvacuations* get_category(ShenandoahAffiliation from, ShenandoahAffiliation to);
64+
65+
ShenandoahEvacuations _young;
66+
ShenandoahEvacuations _old;
67+
ShenandoahEvacuations _promotion;
3768

3869
bool _use_age_table;
3970
AgeTable* _age_table;
@@ -43,11 +74,14 @@ class ShenandoahEvacuationStats : public CHeapObj<mtGC> {
4374

4475
AgeTable* age_table() const;
4576

46-
void begin_evacuation(size_t bytes);
47-
void end_evacuation(size_t bytes);
77+
// Record that the current thread is attempting to copy this many bytes.
78+
void begin_evacuation(size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to);
79+
80+
// Record that the current thread has completed copying this many bytes.
81+
void end_evacuation(size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to);
4882
void record_age(size_t bytes, uint age);
4983

50-
void print_on(outputStream* st);
84+
void print_on(outputStream* st) const;
5185
void accumulate(const ShenandoahEvacuationStats* other);
5286
void reset();
5387
};
@@ -66,8 +100,12 @@ class ShenandoahEvacuationTracker : public CHeapObj<mtGC> {
66100
public:
67101
ShenandoahEvacuationTracker() = default;
68102

69-
void begin_evacuation(Thread* thread, size_t bytes);
70-
void end_evacuation(Thread* thread, size_t bytes);
103+
// Record that the given thread has begun to evacuate an object of this size.
104+
void begin_evacuation(Thread* thread, size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to);
105+
106+
// Multiple threads may attempt to evacuate the same object, but only the successful thread will end the evacuation.
107+
// Evacuations that were begun, but not ended are considered 'abandoned'.
108+
void end_evacuation(Thread* thread, size_t bytes, ShenandoahAffiliation from, ShenandoahAffiliation to);
71109
void record_age(Thread* thread, size_t bytes, uint age);
72110

73111
void print_global_on(outputStream* st);

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

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ size_t ShenandoahGenerationalHeap::unsafe_max_tlab_alloc(Thread *thread) const {
8080
ShenandoahGenerationalHeap::ShenandoahGenerationalHeap(ShenandoahCollectorPolicy* policy) :
8181
ShenandoahHeap(policy),
8282
_age_census(nullptr),
83-
_evac_tracker(new ShenandoahEvacuationTracker()),
8483
_min_plab_size(calculate_min_plab()),
8584
_max_plab_size(calculate_max_plab()),
8685
_regulator_thread(nullptr),
@@ -100,18 +99,6 @@ void ShenandoahGenerationalHeap::print_init_logger() const {
10099
logger.print_all();
101100
}
102101

103-
void ShenandoahGenerationalHeap::print_tracing_info() const {
104-
ShenandoahHeap::print_tracing_info();
105-
106-
LogTarget(Info, gc, stats) lt;
107-
if (lt.is_enabled()) {
108-
LogStream ls(lt);
109-
ls.cr();
110-
ls.cr();
111-
evac_tracker()->print_global_on(&ls);
112-
}
113-
}
114-
115102
void ShenandoahGenerationalHeap::initialize_heuristics() {
116103
// Initialize global generation and heuristics even in generational mode.
117104
ShenandoahHeap::initialize_heuristics();
@@ -338,7 +325,7 @@ oop ShenandoahGenerationalHeap::try_evacuate_object(oop p, Thread* thread, Shena
338325
}
339326

340327
// Copy the object:
341-
NOT_PRODUCT(evac_tracker()->begin_evacuation(thread, size * HeapWordSize));
328+
NOT_PRODUCT(evac_tracker()->begin_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen));
342329
Copy::aligned_disjoint_words(cast_from_oop<HeapWord*>(p), copy, size);
343330
oop copy_val = cast_to_oop(copy);
344331

@@ -360,7 +347,7 @@ oop ShenandoahGenerationalHeap::try_evacuate_object(oop p, Thread* thread, Shena
360347
ContinuationGCSupport::relativize_stack_chunk(copy_val);
361348

362349
// Record that the evacuation succeeded
363-
NOT_PRODUCT(evac_tracker()->end_evacuation(thread, size * HeapWordSize));
350+
NOT_PRODUCT(evac_tracker()->end_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen));
364351

365352
if (target_gen == OLD_GENERATION) {
366353
old_generation()->handle_evacuation(copy, size, from_region->is_young());

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ class ShenandoahGenerationalControlThread;
3636
class ShenandoahAgeCensus;
3737

3838
class ShenandoahGenerationalHeap : public ShenandoahHeap {
39-
void print_tracing_info() const override;
4039
void stop() override;
4140

4241
public:
@@ -66,8 +65,6 @@ class ShenandoahGenerationalHeap : public ShenandoahHeap {
6665
ShenandoahSharedFlag _is_aging_cycle;
6766
// Age census used for adapting tenuring threshold
6867
ShenandoahAgeCensus* _age_census;
69-
// Used primarily to look for failed evacuation attempts.
70-
ShenandoahEvacuationTracker* _evac_tracker;
7168

7269
public:
7370
void set_aging_cycle(bool cond) {
@@ -83,9 +80,6 @@ class ShenandoahGenerationalHeap : public ShenandoahHeap {
8380
return _age_census;
8481
}
8582

86-
ShenandoahEvacuationTracker* evac_tracker() const {
87-
return _evac_tracker;
88-
}
8983

9084
// Ages regions that haven't been used for allocations in the current cycle.
9185
// Resets ages for regions that have been used for allocations.

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,8 @@ ShenandoahHeap::ShenandoahHeap(ShenandoahCollectorPolicy* policy) :
567567
_bitmap_region_special(false),
568568
_aux_bitmap_region_special(false),
569569
_liveness_cache(nullptr),
570-
_collection_set(nullptr)
570+
_collection_set(nullptr),
571+
_evac_tracker(new ShenandoahEvacuationTracker())
571572
{
572573
// Initialize GC mode early, many subsequent initialization procedures depend on it
573574
initialize_mode();
@@ -1352,6 +1353,7 @@ oop ShenandoahHeap::try_evacuate_object(oop p, Thread* thread, ShenandoahHeapReg
13521353
}
13531354

13541355
// Copy the object:
1356+
NOT_PRODUCT(evac_tracker()->begin_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen));
13551357
Copy::aligned_disjoint_words(cast_from_oop<HeapWord*>(p), copy, size);
13561358

13571359
// Try to install the new forwarding pointer.
@@ -1361,6 +1363,7 @@ oop ShenandoahHeap::try_evacuate_object(oop p, Thread* thread, ShenandoahHeapReg
13611363
// Successfully evacuated. Our copy is now the public one!
13621364
ContinuationGCSupport::relativize_stack_chunk(copy_val);
13631365
shenandoah_assert_correct(nullptr, copy_val);
1366+
NOT_PRODUCT(evac_tracker()->end_evacuation(thread, size * HeapWordSize, from_region->affiliation(), target_gen));
13641367
return copy_val;
13651368
} else {
13661369
// Failed to evacuate. We need to deal with the object that is left behind. Since this
@@ -1590,6 +1593,13 @@ void ShenandoahHeap::print_tracing_info() const {
15901593
ResourceMark rm;
15911594
LogStream ls(lt);
15921595

1596+
#ifdef NOT_PRODUCT
1597+
evac_tracker()->print_global_on(&ls);
1598+
1599+
ls.cr();
1600+
ls.cr();
1601+
#endif
1602+
15931603
phase_timings()->print_global_on(&ls);
15941604

15951605
ls.cr();

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,10 @@ class ShenandoahHeap : public CollectedHeap {
557557

558558
ShenandoahEvacOOMHandler* oom_evac_handler() { return &_oom_evac_handler; }
559559

560+
ShenandoahEvacuationTracker* evac_tracker() const {
561+
return _evac_tracker;
562+
}
563+
560564
void on_cycle_start(GCCause::Cause cause, ShenandoahGeneration* generation);
561565
void on_cycle_end(ShenandoahGeneration* generation);
562566

@@ -789,6 +793,10 @@ class ShenandoahHeap : public CollectedHeap {
789793

790794
oop try_evacuate_object(oop src, Thread* thread, ShenandoahHeapRegion* from_region, ShenandoahAffiliation target_gen);
791795

796+
protected:
797+
// Used primarily to look for failed evacuation attempts.
798+
ShenandoahEvacuationTracker* _evac_tracker;
799+
792800
public:
793801
static address in_cset_fast_test_addr();
794802

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,7 @@ ShenandoahThreadLocalData::ShenandoahThreadLocalData() :
4444
_plab_promoted(0),
4545
_plab_allows_promotion(true),
4646
_plab_retries_enabled(true),
47-
_evacuation_stats(nullptr) {
48-
if (ShenandoahHeap::heap()->mode()->is_generational()) {
49-
_evacuation_stats = new ShenandoahEvacuationStats();
50-
}
47+
_evacuation_stats(new ShenandoahEvacuationStats()) {
5148
}
5249

5350
ShenandoahThreadLocalData::~ShenandoahThreadLocalData() {

0 commit comments

Comments
 (0)