Skip to content

Commit 7a89ffe

Browse files
author
Thomas Schatzl
committedJul 15, 2021
8270014: Add scoped objects for g1 young gc verification and young gc internal timing
Reviewed-by: ayang, iwalulya, kbarrett
1 parent 793d772 commit 7a89ffe

File tree

7 files changed

+76
-46
lines changed

7 files changed

+76
-46
lines changed
 

‎src/hotspot/share/gc/g1/g1CollectedHeap.cpp

+40-17
Original file line numberDiff line numberDiff line change
@@ -2922,6 +2922,36 @@ class G1YoungGCTraceTime {
29222922
}
29232923
};
29242924

2925+
class G1YoungGCVerifierMark : public StackObj {
2926+
G1HeapVerifier::G1VerifyType _type;
2927+
2928+
static G1HeapVerifier::G1VerifyType young_collection_verify_type() {
2929+
G1CollectorState* state = G1CollectedHeap::heap()->collector_state();
2930+
if (state->in_concurrent_start_gc()) {
2931+
return G1HeapVerifier::G1VerifyConcurrentStart;
2932+
} else if (state->in_young_only_phase()) {
2933+
return G1HeapVerifier::G1VerifyYoungNormal;
2934+
} else {
2935+
return G1HeapVerifier::G1VerifyMixed;
2936+
}
2937+
}
2938+
2939+
public:
2940+
G1YoungGCVerifierMark() : _type(young_collection_verify_type()) {
2941+
G1CollectedHeap::heap()->verify_before_young_collection(_type);
2942+
}
2943+
2944+
~G1YoungGCVerifierMark() {
2945+
G1CollectedHeap::heap()->verify_after_young_collection(_type);
2946+
}
2947+
};
2948+
2949+
class G1YoungGCNotifyPauseMark : public StackObj {
2950+
public:
2951+
G1YoungGCNotifyPauseMark() { G1CollectedHeap::heap()->policy()->record_young_gc_pause_start(); }
2952+
~G1YoungGCNotifyPauseMark() { G1CollectedHeap::heap()->policy()->record_young_gc_pause_end(); }
2953+
};
2954+
29252955
G1HeapPrinterMark::G1HeapPrinterMark(G1CollectedHeap* g1h) : _g1h(g1h), _heap_transition(g1h) {
29262956
// This summary needs to be printed before incrementing total collections.
29272957
_g1h->rem_set()->print_periodic_summary_info("Before GC RS summary", _g1h->total_collections());
@@ -3053,8 +3083,8 @@ void G1CollectedHeap::do_collection_pause_at_safepoint_helper(double target_paus
30533083
// determining collector state.
30543084
G1YoungGCTraceTime tm(gc_cause());
30553085

3056-
// Young GC internal timing
3057-
policy()->note_gc_start();
3086+
// Young GC internal pause timing
3087+
G1YoungGCNotifyPauseMark npm;
30583088
// JFR
30593089
G1YoungGCJFRTracerMark jtm(_gc_timer_stw, _gc_tracer_stw, gc_cause());
30603090
// JStat/MXBeans
@@ -3069,15 +3099,14 @@ void G1CollectedHeap::do_collection_pause_at_safepoint_helper(double target_paus
30693099
// just to do that).
30703100
wait_for_root_region_scanning();
30713101

3072-
G1HeapVerifier::G1VerifyType verify_type = young_collection_verify_type();
3073-
verify_before_young_collection(verify_type);
3102+
G1YoungGCVerifierMark vm;
30743103
{
30753104
// Actual collection work starts and is executed (only) in this scope.
30763105

3077-
// The elapsed time induced by the start time below deliberately elides
3078-
// the possible verification above.
3079-
double sample_start_time_sec = os::elapsedTime();
3080-
policy()->record_collection_pause_start(sample_start_time_sec);
3106+
// Young GC internal collection timing. The elapsed time recorded in the
3107+
// policy for the collection deliberately elides verification (and some
3108+
// other trivial setup above).
3109+
policy()->record_young_collection_start();
30813110

30823111
calculate_collection_set(jtm.evacuation_info(), target_pause_time_ms);
30833112

@@ -3106,14 +3135,8 @@ void G1CollectedHeap::do_collection_pause_at_safepoint_helper(double target_paus
31063135
// modifies it to the next state.
31073136
jtm.report_pause_type(collector_state()->young_gc_pause_type(concurrent_operation_is_full_mark));
31083137

3109-
double sample_end_time_sec = os::elapsedTime();
3110-
double pause_time_ms = (sample_end_time_sec - sample_start_time_sec) * MILLIUNITS;
3111-
policy()->record_collection_pause_end(pause_time_ms, concurrent_operation_is_full_mark);
3138+
policy()->record_young_collection_end(concurrent_operation_is_full_mark);
31123139
}
3113-
verify_after_young_collection(verify_type);
3114-
3115-
policy()->print_phases();
3116-
31173140
TASKQUEUE_STATS_ONLY(print_taskqueue_stats());
31183141
TASKQUEUE_STATS_ONLY(reset_taskqueue_stats());
31193142
}
@@ -3780,11 +3803,11 @@ void G1CollectedHeap::evacuate_next_optional_regions(G1ParScanThreadStateSet* pe
37803803
}
37813804

37823805
void G1CollectedHeap::evacuate_optional_collection_set(G1ParScanThreadStateSet* per_thread_states) {
3783-
const double gc_start_time_ms = phase_times()->cur_collection_start_sec() * 1000.0;
3806+
const double collection_start_time_ms = phase_times()->cur_collection_start_sec() * 1000.0;
37843807

37853808
while (!evacuation_failed() && _collection_set.optional_region_length() > 0) {
37863809

3787-
double time_used_ms = os::elapsedTime() * 1000.0 - gc_start_time_ms;
3810+
double time_used_ms = os::elapsedTime() * 1000.0 - collection_start_time_ms;
37883811
double time_left_ms = MaxGCPauseMillis - time_used_ms;
37893812

37903813
if (time_left_ms < 0 ||

‎src/hotspot/share/gc/g1/g1CollectedHeap.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ class G1CollectedHeap : public CollectedHeap {
146146
friend class G1GCAllocRegion;
147147
friend class G1HeapVerifier;
148148

149+
friend class G1YoungGCVerifierMark;
150+
149151
// Closures used in implementation.
150152
friend class G1ParScanThreadState;
151153
friend class G1ParScanThreadStateSet;

‎src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ void G1GCPhaseTimes::reset() {
192192
_weak_phase_times.reset();
193193
}
194194

195-
void G1GCPhaseTimes::note_gc_start() {
195+
void G1GCPhaseTimes::record_gc_pause_start() {
196196
_gc_start_counter = os::elapsed_counter();
197197
reset();
198198
}
@@ -211,7 +211,7 @@ double G1GCPhaseTimes::worker_time(GCParPhases phase, uint worker) {
211211
return 0.0;
212212
}
213213

214-
void G1GCPhaseTimes::note_gc_end() {
214+
void G1GCPhaseTimes::record_gc_pause_end() {
215215
_gc_pause_time_ms = TimeHelper::counter_to_millis(os::elapsed_counter() - _gc_start_counter);
216216

217217
double uninitialized = WorkerDataArray<double>::uninitialized();
@@ -519,8 +519,9 @@ void G1GCPhaseTimes::print_other(double accounted_ms) const {
519519
}
520520

521521
void G1GCPhaseTimes::print() {
522-
note_gc_end();
523-
522+
// Check if some time has been recorded for verification and only then print
523+
// the message. We do not use Verify*GC here to print because VerifyGCType
524+
// further limits actual verification.
524525
if (_cur_verify_before_time_ms > 0.0) {
525526
debug_time("Verify Before", _cur_verify_before_time_ms);
526527
}
@@ -532,6 +533,7 @@ void G1GCPhaseTimes::print() {
532533
accounted_ms += print_post_evacuate_collection_set();
533534
print_other(accounted_ms);
534535

536+
// See above comment on the _cur_verify_before_time_ms check.
535537
if (_cur_verify_after_time_ms > 0.0) {
536538
debug_time("Verify After", _cur_verify_after_time_ms);
537539
}

‎src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,6 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
206206
WeakProcessorTimes _weak_phase_times;
207207

208208
double worker_time(GCParPhases phase, uint worker);
209-
void note_gc_end();
210209
void reset();
211210

212211
template <class T>
@@ -234,7 +233,8 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
234233

235234
public:
236235
G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads);
237-
void note_gc_start();
236+
void record_gc_pause_start();
237+
void record_gc_pause_end();
238238
void print();
239239
static const char* phase_name(GCParPhases phase);
240240

‎src/hotspot/share/gc/g1/g1Policy.cpp

+12-9
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ void G1Policy::init(G1CollectedHeap* g1h, G1CollectionSet* collection_set) {
113113
_collection_set->start_incremental_building();
114114
}
115115

116-
void G1Policy::note_gc_start() {
117-
phase_times()->note_gc_start();
116+
void G1Policy::record_young_gc_pause_start() {
117+
phase_times()->record_gc_pause_start();
118118
}
119119

120120
class G1YoungLengthPredictor {
@@ -517,7 +517,8 @@ void G1Policy::record_concurrent_refinement_stats() {
517517
}
518518
}
519519

520-
void G1Policy::record_collection_pause_start(double start_time_sec) {
520+
void G1Policy::record_young_collection_start() {
521+
Ticks now = Ticks::now();
521522
// We only need to do this here as the policy will only be applied
522523
// to the GC we're about to start. so, no point is calculating this
523524
// every time we calculate / recalculate the target young length.
@@ -528,7 +529,7 @@ void G1Policy::record_collection_pause_start(double start_time_sec) {
528529
max_survivor_regions(), _g1h->num_used_regions(), _g1h->max_regions());
529530
assert_used_and_recalculate_used_equal(_g1h);
530531

531-
phase_times()->record_cur_collection_start_sec(start_time_sec);
532+
phase_times()->record_cur_collection_start_sec(now.seconds());
532533

533534
record_concurrent_refinement_stats();
534535

@@ -628,11 +629,12 @@ double G1Policy::logged_cards_processing_time() const {
628629
// Anything below that is considered to be zero
629630
#define MIN_TIMER_GRANULARITY 0.0000001
630631

631-
void G1Policy::record_collection_pause_end(double pause_time_ms, bool concurrent_operation_is_full_mark) {
632+
void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mark) {
632633
G1GCPhaseTimes* p = phase_times();
633634

634-
double end_time_sec = os::elapsedTime();
635635
double start_time_sec = phase_times()->cur_collection_start_sec();
636+
double end_time_sec = Ticks::now().seconds();
637+
double pause_time_ms = (end_time_sec - start_time_sec) * 1000.0;
636638

637639
G1GCPauseType this_pause = collector_state()->young_gc_pause_type(concurrent_operation_is_full_mark);
638640

@@ -889,7 +891,8 @@ void G1Policy::report_ihop_statistics() {
889891
_ihop_control->print();
890892
}
891893

892-
void G1Policy::print_phases() {
894+
void G1Policy::record_young_gc_pause_end() {
895+
phase_times()->record_gc_pause_end();
893896
phase_times()->print();
894897
}
895898

@@ -1487,7 +1490,7 @@ void G1Policy::update_survival_estimates_for_next_collection() {
14871490
}
14881491

14891492
void G1Policy::transfer_survivors_to_cset(const G1SurvivorRegions* survivors) {
1490-
note_start_adding_survivor_regions();
1493+
start_adding_survivor_regions();
14911494

14921495
HeapRegion* last = NULL;
14931496
for (GrowableArrayIterator<HeapRegion*> it = survivors->regions()->begin();
@@ -1503,7 +1506,7 @@ void G1Policy::transfer_survivors_to_cset(const G1SurvivorRegions* survivors) {
15031506

15041507
last = curr;
15051508
}
1506-
note_stop_adding_survivor_regions();
1509+
stop_adding_survivor_regions();
15071510

15081511
// Don't clear the survivor list handles until the start of
15091512
// the next evacuation pause - we need it in order to re-tag

‎src/hotspot/share/gc/g1/g1Policy.hpp

+8-8
Original file line numberDiff line numberDiff line change
@@ -301,17 +301,19 @@ class G1Policy: public CHeapObj<mtGC> {
301301

302302
void init(G1CollectedHeap* g1h, G1CollectionSet* collection_set);
303303

304-
void note_gc_start();
304+
// Record the start and end of the young gc pause.
305+
void record_young_gc_pause_start();
306+
void record_young_gc_pause_end();
305307

306308
bool need_to_start_conc_mark(const char* source, size_t alloc_word_size = 0);
307309

308310
bool concurrent_operation_is_full_mark(const char* msg = NULL);
309311

310312
bool about_to_start_mixed_phase() const;
311313

312-
// Record the start and end of an evacuation pause.
313-
void record_collection_pause_start(double start_time_sec);
314-
void record_collection_pause_end(double pause_time_ms, bool concurrent_operation_is_full_mark);
314+
// Record the start and end of the actual collection part of the evacuation pause.
315+
void record_young_collection_start();
316+
void record_young_collection_end(bool concurrent_operation_is_full_mark);
315317

316318
// Record the start and end of a full collection.
317319
void record_full_collection_start();
@@ -328,8 +330,6 @@ class G1Policy: public CHeapObj<mtGC> {
328330
void record_concurrent_mark_cleanup_start();
329331
void record_concurrent_mark_cleanup_end(bool has_rebuilt_remembered_sets);
330332

331-
void print_phases();
332-
333333
bool next_gc_should_be_mixed(const char* true_action_str,
334334
const char* false_action_str) const;
335335

@@ -427,11 +427,11 @@ class G1Policy: public CHeapObj<mtGC> {
427427
return _max_survivor_regions;
428428
}
429429

430-
void note_start_adding_survivor_regions() {
430+
void start_adding_survivor_regions() {
431431
_survivor_surv_rate_group->start_adding_regions();
432432
}
433433

434-
void note_stop_adding_survivor_regions() {
434+
void stop_adding_survivor_regions() {
435435
_survivor_surv_rate_group->stop_adding_regions();
436436
}
437437

‎test/hotspot/jtreg/gc/g1/TestEagerReclaimHumongousRegionsLog.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,12 @@ public static void runTest() throws Exception {
7373

7474
// This gives an array of lines containing eager reclaim of humongous regions
7575
// log messages contents after the ":" in the following order for every GC:
76+
// Humongous Regions: f->g
7677
// Region Register: a.ams
7778
// Eagerly Reclaim Humonguous Objects b.cms
7879
// Humongous Total: Min: 1, Avg: 1.0, Max: 1, Diff: 0, Sum: c, Workers: 1
7980
// Humongous Candidate: Min: 1, Avg: 1.0, Max: 1, Diff: 0, Sum: d, Workers: 1
8081
// Humongous Reclaimed: Min: 1, Avg: 1.0, Max: 1, Diff: 0, Sum: e, Workers: 1
81-
// Humongous Regions: f->g
8282

8383
String[] lines = Arrays.stream(output.getStdout().split("\\R"))
8484
.filter(s -> (s.contains("Humongous") || s.contains("Region Register"))).map(s -> s.substring(s.indexOf(LogSeparator) + LogSeparator.length()))
@@ -87,12 +87,12 @@ public static void runTest() throws Exception {
8787
Asserts.assertTrue(lines.length % 6 == 0, "There seems to be an unexpected amount of log messages (total: " + lines.length + ") per GC");
8888

8989
for (int i = 0; i < lines.length; i += 6) {
90-
int total = Integer.parseInt(getSumValue(lines[i + 2]));
91-
int candidate = Integer.parseInt(getSumValue(lines[i + 3]));
92-
int reclaimed = Integer.parseInt(getSumValue(lines[i + 4]));
90+
int total = Integer.parseInt(getSumValue(lines[i + 3]));
91+
int candidate = Integer.parseInt(getSumValue(lines[i + 4]));
92+
int reclaimed = Integer.parseInt(getSumValue(lines[i + 5]));
9393

94-
int before = Integer.parseInt(lines[i + 5].substring(0, 1));
95-
int after = Integer.parseInt(lines[i + 5].substring(3, 4));
94+
int before = Integer.parseInt(lines[i].substring(0, 1));
95+
int after = Integer.parseInt(lines[i].substring(3, 4));
9696
System.out.println("total " + total + " candidate " + candidate + " reclaimed " + reclaimed + " before " + before + " after " + after);
9797

9898
Asserts.assertEQ(total, candidate, "Not all humonguous objects are candidates");

0 commit comments

Comments
 (0)
Please sign in to comment.