Skip to content

Commit 124575b

Browse files
author
Ivan Walulya
committed
8359348: G1: Improve cpu usage measurements for heap sizing
Reviewed-by: tschatzl, ayang, manc
1 parent 32df2d1 commit 124575b

File tree

5 files changed

+76
-27
lines changed

5 files changed

+76
-27
lines changed

src/hotspot/share/gc/g1/g1Analytics.cpp

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "gc/shared/gc_globals.hpp"
2929
#include "runtime/globals.hpp"
3030
#include "runtime/os.hpp"
31+
#include "services/cpuTimeUsage.hpp"
3132
#include "utilities/debug.hpp"
3233
#include "utilities/globalDefinitions.hpp"
3334
#include "utilities/numberSeq.hpp"
@@ -73,6 +74,8 @@ G1Analytics::G1Analytics(const G1Predictions* predictor) :
7374
_concurrent_mark_cleanup_times_ms(NumPrevPausesForHeuristics),
7475
_alloc_rate_ms_seq(TruncatedSeqLength),
7576
_prev_collection_pause_end_ms(0.0),
77+
_gc_cpu_time_at_pause_end_ms(),
78+
_concurrent_gc_cpu_time_ms(),
7679
_concurrent_refine_rate_ms_seq(TruncatedSeqLength),
7780
_dirtied_cards_rate_ms_seq(TruncatedSeqLength),
7881
_dirtied_cards_in_thread_buffers_seq(TruncatedSeqLength),
@@ -88,8 +91,8 @@ G1Analytics::G1Analytics(const G1Predictions* predictor) :
8891
_young_other_cost_per_region_ms_seq(TruncatedSeqLength),
8992
_non_young_other_cost_per_region_ms_seq(TruncatedSeqLength),
9093
_recent_prev_end_times_for_all_gcs_sec(NumPrevPausesForHeuristics),
91-
_long_term_pause_time_ratio(0.0),
92-
_short_term_pause_time_ratio(0.0) {
94+
_long_term_gc_time_ratio(0.0),
95+
_short_term_gc_time_ratio(0.0) {
9396

9497
// Seed sequences with initial values.
9598
_recent_prev_end_times_for_all_gcs_sec.add(os::elapsedTime());
@@ -149,6 +152,10 @@ int G1Analytics::num_alloc_rate_ms() const {
149152
return _alloc_rate_ms_seq.num();
150153
}
151154

155+
double G1Analytics::gc_cpu_time_ms() const {
156+
return (double)CPUTimeUsage::GC::gc_threads() / NANOSECS_PER_MILLISEC;
157+
}
158+
152159
void G1Analytics::report_concurrent_mark_remark_times_ms(double ms) {
153160
_concurrent_mark_remark_times_ms.add(ms);
154161
}
@@ -157,15 +164,27 @@ void G1Analytics::report_alloc_rate_ms(double alloc_rate) {
157164
_alloc_rate_ms_seq.add(alloc_rate);
158165
}
159166

160-
void G1Analytics::compute_pause_time_ratios(double end_time_sec, double pause_time_ms) {
167+
void G1Analytics::update_gc_time_ratios(double end_time_sec, double pause_time_ms) {
168+
// This estimates the wall-clock time "lost" by application mutator threads due to concurrent GC
169+
// activity. We do not account for contention on other shared resources such as memory bandwidth and
170+
// caches, therefore underestimate the impact of the concurrent GC activity on mutator threads.
171+
uint num_cpus = (uint)os::active_processor_count();
172+
double concurrent_gc_impact_time = _concurrent_gc_cpu_time_ms / num_cpus;
173+
174+
double gc_time_ms = pause_time_ms + concurrent_gc_impact_time;
175+
161176
double long_interval_ms = (end_time_sec - oldest_known_gc_end_time_sec()) * 1000.0;
162-
double gc_pause_time_ms = _recent_gc_times_ms.sum() - _recent_gc_times_ms.oldest() + pause_time_ms;
163-
_long_term_pause_time_ratio = gc_pause_time_ms / long_interval_ms;
164-
_long_term_pause_time_ratio = clamp(_long_term_pause_time_ratio, 0.0, 1.0);
177+
double long_term_gc_time_ms = _recent_gc_times_ms.sum() - _recent_gc_times_ms.oldest() + gc_time_ms;
178+
179+
_long_term_gc_time_ratio = long_term_gc_time_ms / long_interval_ms;
180+
_long_term_gc_time_ratio = clamp(_long_term_gc_time_ratio, 0.0, 1.0);
165181

166182
double short_interval_ms = (end_time_sec - most_recent_gc_end_time_sec()) * 1000.0;
167-
_short_term_pause_time_ratio = pause_time_ms / short_interval_ms;
168-
_short_term_pause_time_ratio = clamp(_short_term_pause_time_ratio, 0.0, 1.0);
183+
184+
_short_term_gc_time_ratio = gc_time_ms / short_interval_ms;
185+
_short_term_gc_time_ratio = clamp(_short_term_gc_time_ratio, 0.0, 1.0);
186+
187+
update_recent_gc_times(end_time_sec, gc_time_ms);
169188
}
170189

171190
void G1Analytics::report_concurrent_refine_rate_ms(double cards_per_ms) {
@@ -305,8 +324,8 @@ double G1Analytics::most_recent_gc_end_time_sec() const {
305324
}
306325

307326
void G1Analytics::update_recent_gc_times(double end_time_sec,
308-
double pause_time_ms) {
309-
_recent_gc_times_ms.add(pause_time_ms);
327+
double gc_time_ms) {
328+
_recent_gc_times_ms.add(gc_time_ms);
310329
_recent_prev_end_times_for_all_gcs_sec.add(end_time_sec);
311330
}
312331

src/hotspot/share/gc/g1/g1Analytics.hpp

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,15 @@ class G1Analytics: public CHeapObj<mtGC> {
4444
TruncatedSeq _concurrent_mark_cleanup_times_ms;
4545

4646
TruncatedSeq _alloc_rate_ms_seq;
47-
double _prev_collection_pause_end_ms;
47+
double _prev_collection_pause_end_ms;
48+
49+
// Records the total GC CPU time (in ms) at the end of the last GC pause.
50+
// Used as a baseline to calculate CPU time spent in GC threads between pauses.
51+
double _gc_cpu_time_at_pause_end_ms;
52+
53+
// CPU time (ms) spent by GC threads between the end of the last pause
54+
// and the start of the current pause; calculated at start of a GC pause.
55+
double _concurrent_gc_cpu_time_ms;
4856

4957
TruncatedSeq _concurrent_refine_rate_ms_seq;
5058
TruncatedSeq _dirtied_cards_rate_ms_seq;
@@ -75,10 +83,10 @@ class G1Analytics: public CHeapObj<mtGC> {
7583
// Statistics kept per GC stoppage, pause or full.
7684
TruncatedSeq _recent_prev_end_times_for_all_gcs_sec;
7785

78-
// Cached values for long and short term pause time ratios. See
79-
// compute_pause_time_ratios() for how they are computed.
80-
double _long_term_pause_time_ratio;
81-
double _short_term_pause_time_ratio;
86+
// Cached values for long and short term gc time ratios. See
87+
// update_gc_time_ratios() for how they are computed.
88+
double _long_term_gc_time_ratio;
89+
double _short_term_gc_time_ratio;
8290

8391
double predict_in_unit_interval(TruncatedSeq const* seq) const;
8492
size_t predict_size(TruncatedSeq const* seq) const;
@@ -102,12 +110,12 @@ class G1Analytics: public CHeapObj<mtGC> {
102110
return _prev_collection_pause_end_ms;
103111
}
104112

105-
double long_term_pause_time_ratio() const {
106-
return _long_term_pause_time_ratio;
113+
double long_term_gc_time_ratio() const {
114+
return _long_term_gc_time_ratio;
107115
}
108116

109-
double short_term_pause_time_ratio() const {
110-
return _short_term_pause_time_ratio;
117+
double short_term_gc_time_ratio() const {
118+
return _short_term_gc_time_ratio;
111119
}
112120

113121
static constexpr uint max_num_of_recorded_pause_times() {
@@ -122,6 +130,20 @@ class G1Analytics: public CHeapObj<mtGC> {
122130
_prev_collection_pause_end_ms = ms;
123131
}
124132

133+
void set_gc_cpu_time_at_pause_end_ms(double ms) {
134+
_gc_cpu_time_at_pause_end_ms = ms;
135+
}
136+
137+
double gc_cpu_time_at_pause_end_ms() const {
138+
return _gc_cpu_time_at_pause_end_ms;
139+
}
140+
141+
void set_concurrent_gc_cpu_time_ms(double ms) {
142+
_concurrent_gc_cpu_time_ms = ms;
143+
}
144+
145+
double gc_cpu_time_ms() const;
146+
125147
void report_concurrent_mark_remark_times_ms(double ms);
126148
void report_concurrent_mark_cleanup_times_ms(double ms);
127149
void report_alloc_rate_ms(double alloc_rate);
@@ -173,8 +195,8 @@ class G1Analytics: public CHeapObj<mtGC> {
173195
size_t predict_pending_cards(bool for_young_only_phase) const;
174196

175197
// Add a new GC of the given duration and end time to the record.
176-
void update_recent_gc_times(double end_time_sec, double elapsed_ms);
177-
void compute_pause_time_ratios(double end_time_sec, double pause_time_ms);
198+
void update_recent_gc_times(double end_time_sec, double gc_time_ms);
199+
void update_gc_time_ratios(double end_time_sec, double pause_time_ms);
178200
};
179201

180202
#endif // SHARE_GC_G1_G1ANALYTICS_HPP

src/hotspot/share/gc/g1/g1HeapSizingPolicy.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,8 @@ size_t G1HeapSizingPolicy::young_collection_resize_amount(bool& expand, size_t a
217217
assert(GCTimeRatio > 0, "must be");
218218
expand = false;
219219

220-
const double long_term_gc_cpu_usage = _analytics->long_term_pause_time_ratio();
221-
const double short_term_gc_cpu_usage = _analytics->short_term_pause_time_ratio();
220+
const double long_term_gc_cpu_usage = _analytics->long_term_gc_time_ratio();
221+
const double short_term_gc_cpu_usage = _analytics->short_term_gc_time_ratio();
222222

223223
double gc_cpu_usage_target = 1.0 / (1.0 + GCTimeRatio);
224224
gc_cpu_usage_target = scale_with_heap(gc_cpu_usage_target);

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,12 @@ bool G1Policy::should_retain_evac_failed_region(uint index) const {
664664
void G1Policy::record_pause_start_time() {
665665
Ticks now = Ticks::now();
666666
_cur_pause_start_sec = now.seconds();
667+
668+
double prev_gc_cpu_pause_end_ms = _analytics->gc_cpu_time_at_pause_end_ms();
669+
double cur_gc_cpu_time_ms = _analytics->gc_cpu_time_ms();
670+
671+
double concurrent_gc_cpu_time_ms = cur_gc_cpu_time_ms - prev_gc_cpu_pause_end_ms;
672+
_analytics->set_concurrent_gc_cpu_time_ms(concurrent_gc_cpu_time_ms);
667673
}
668674

669675
void G1Policy::record_young_collection_start() {
@@ -1346,8 +1352,7 @@ void G1Policy::update_gc_pause_time_ratios(G1GCPauseType gc_type, double start_t
13461352
double pause_time_sec = end_time_sec - start_time_sec;
13471353
double pause_time_ms = pause_time_sec * 1000.0;
13481354

1349-
_analytics->compute_pause_time_ratios(end_time_sec, pause_time_ms);
1350-
_analytics->update_recent_gc_times(end_time_sec, pause_time_ms);
1355+
_analytics->update_gc_time_ratios(end_time_sec, pause_time_ms);
13511356

13521357
if (gc_type == G1GCPauseType::Cleanup || gc_type == G1GCPauseType::Remark) {
13531358
_analytics->append_prev_collection_pause_end_ms(pause_time_ms);
@@ -1370,6 +1375,9 @@ void G1Policy::record_pause(G1GCPauseType gc_type,
13701375
}
13711376

13721377
update_time_to_mixed_tracking(gc_type, start, end);
1378+
1379+
double elapsed_gc_cpu_time = _analytics->gc_cpu_time_ms();
1380+
_analytics->set_gc_cpu_time_at_pause_end_ms(elapsed_gc_cpu_time);
13731381
}
13741382

13751383
void G1Policy::update_time_to_mixed_tracking(G1GCPauseType gc_type,

test/hotspot/gtest/gc/g1/test_g1Analytics.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@
2929
TEST_VM(G1Analytics, is_initialized) {
3030
G1Predictions p(0.888888); // the actual sigma value doesn't matter
3131
G1Analytics a(&p);
32-
ASSERT_EQ(a.long_term_pause_time_ratio(), 0.0);
33-
ASSERT_EQ(a.short_term_pause_time_ratio(), 0.0);
32+
ASSERT_EQ(a.long_term_gc_time_ratio(), 0.0);
33+
ASSERT_EQ(a.short_term_gc_time_ratio(), 0.0);
3434
}

0 commit comments

Comments
 (0)