Skip to content

Commit e3f43fa

Browse files
committed
Merge branch 'master' into dragonwell_extended-8.20.21
2 parents 788fa8a + e7793b1 commit e3f43fa

File tree

15 files changed

+588
-104
lines changed

15 files changed

+588
-104
lines changed

hotspot/src/share/vm/code/dependencies.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -1578,6 +1578,10 @@ static bool overrides(Method* sub_m, Method* base_m) {
15781578
// Include m itself in the set, unless it is abstract.
15791579
// If this set has exactly one element, return that element.
15801580
Method* Dependencies::find_unique_concrete_method(Klass* ctxk, Method* m) {
1581+
// Return NULL if m is marked old; must have been a redefined method.
1582+
if (m->is_old()) {
1583+
return NULL;
1584+
}
15811585
ClassHierarchyWalker wf(m);
15821586
assert(wf.check_method_context(ctxk, m), "proper context");
15831587
wf.record_witnesses(1);

hotspot/src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp

+317
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,278 @@
3737

3838
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
3939

40+
class IOPolicy : public CHeapObj<mtGC> {
41+
class IOWaitRecord {
42+
public:
43+
IOWaitRecord(bool *active) : _active(active), _last_cpu_total(0), _last_cpu_iowait(0) {}
44+
void start() {
45+
fill_value(&_last_cpu_total, &_last_cpu_iowait);
46+
}
47+
double stop() {
48+
size_t total, iowait;
49+
fill_value(&total, &iowait);
50+
51+
size_t total_diff = total - _last_cpu_total;
52+
size_t iowait_diff = iowait - _last_cpu_iowait;
53+
if (total_diff == 0) {
54+
if (PrintAdaptiveSizePolicy) {
55+
gclog_or_tty->print_cr("fail to record, cpu total diff is 0");
56+
}
57+
return 0;
58+
} else {
59+
return (double)iowait_diff / (double)total_diff;
60+
}
61+
}
62+
private:
63+
// if anything unexpected happened during record, we will deactivate the policy
64+
bool *_active;
65+
size_t _last_cpu_total;
66+
size_t _last_cpu_iowait;
67+
void fill_value_fail(FILE *file) {
68+
if (file != NULL) {
69+
fclose(file);
70+
}
71+
warning("Deactivate UseIOPrioritySizePolicy due to failed to parse cpu stat");
72+
*_active = false;
73+
}
74+
void fill_value(size_t *total, size_t *iowait) {
75+
FILE *file = fopen("/proc/stat", "r");
76+
if (file == NULL) {
77+
fill_value_fail(file);
78+
return;
79+
}
80+
81+
char line[256];
82+
char *read_line = fgets(line, sizeof(line), file);
83+
if (read_line == NULL) {
84+
fill_value_fail(file);
85+
return;
86+
}
87+
88+
/*
89+
* Expected stdout of the first line of /proc/stat should be like:
90+
* cat /proc/stat
91+
* cpu 417487649 75106 102895030 23107566512 152075 65480092 6013218 0 0 0
92+
*/
93+
size_t user, nice, system, idle, iowait_time, irq, softirq, steal, guest, guest_nice;
94+
int parse_line = sscanf(line, "cpu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", &user,
95+
&nice, &system, &idle, &iowait_time, &irq, &softirq, &steal, &guest, &guest_nice);
96+
if (parse_line != 10) {
97+
fill_value_fail(file);
98+
return;
99+
}
100+
101+
*total = user + nice + system + idle + iowait_time + irq + softirq + steal + guest + guest_nice;
102+
*iowait = iowait_time;
103+
fclose(file);
104+
}
105+
};
106+
107+
class UserTimeRecord {
108+
public:
109+
UserTimeRecord(bool *active) : _active(active), _starting_user_time(0), _starting_system_time(0), _starting_real_time(0) {}
110+
void start() {
111+
if (!os::getTimesSecs(&_starting_real_time, &_starting_user_time, &_starting_system_time)) {
112+
warning("Deactivate UseIOPrioritySizePolicy due to failed to get cpu times");
113+
*_active = false;
114+
}
115+
}
116+
double stop() {
117+
const static double INVALID = 99999;
118+
double real_time, user_time, system_time;
119+
if (!os::getTimesSecs(&real_time, &user_time, &system_time)) {
120+
warning("Deactivate UseIOPrioritySizePolicy due to failed to get cpu times");
121+
*_active = false;
122+
return INVALID;
123+
}
124+
double user_diff = user_time - _starting_user_time;
125+
double real_diff = real_time - _starting_real_time;
126+
// too short interval to calculate a meaningful user time percent, thus we
127+
// return a very large number to avoid trigger memory reduction.
128+
if (real_diff < 0.00001) {
129+
if (PrintAdaptiveSizePolicy) {
130+
gclog_or_tty->print_cr("fail to record, real_duration too small: %f",
131+
real_diff);
132+
}
133+
return INVALID;
134+
}
135+
return user_diff / real_diff;
136+
}
137+
private:
138+
// if anything unexpected happened during record, we will deactivate the policy
139+
bool *_active;
140+
double _starting_user_time;
141+
double _starting_system_time;
142+
double _starting_real_time;
143+
};
144+
145+
double _default_throughput_goal;
146+
147+
double _mutator_iowait_percent;
148+
double _mutator_user_percent;
149+
elapsedTimer _io_triggerred_major_gc_timer;
150+
151+
IOWaitRecord _io_wait_record;
152+
UserTimeRecord _user_time_record;
153+
154+
bool _active;
155+
bool _should_reduce_heap;
156+
157+
public:
158+
IOPolicy(double default_throughput_goal) :
159+
_default_throughput_goal(default_throughput_goal),
160+
_mutator_iowait_percent(0.0),
161+
_mutator_user_percent(0.0),
162+
_io_triggerred_major_gc_timer(),
163+
_io_wait_record(&_active),
164+
_user_time_record(&_active),
165+
_active(true),
166+
_should_reduce_heap(false) {
167+
_io_triggerred_major_gc_timer.start();
168+
start_mutator_record();
169+
if (FLAG_IS_CMDLINE(NewSize)) {
170+
if (PrintAdaptiveSizePolicy) {
171+
gclog_or_tty->print_cr("NewSize or Xmn is set, which may introduce a large size for min young size");
172+
}
173+
}
174+
if (MaxHeapSize == InitialHeapSize) {
175+
if (PrintAdaptiveSizePolicy) {
176+
gclog_or_tty->print_cr("Xmx is equal to Xms, which may introduce a large size for min young size");
177+
}
178+
}
179+
if (PrintAdaptiveSizePolicy) {
180+
gclog_or_tty->print_cr(
181+
"min size: young " SIZE_FORMAT "M, old " SIZE_FORMAT
182+
"M. IOPrioritySizePolicy can't decrease heap below these sizes",
183+
ParallelScavengeHeap::young_gen()->min_gen_size() / M,
184+
ParallelScavengeHeap::old_gen()->min_gen_size() / M);
185+
}
186+
}
187+
188+
void start_mutator_record() {
189+
if (!_active) {
190+
return;
191+
}
192+
_io_wait_record.start();
193+
_user_time_record.start();
194+
}
195+
196+
void stop_mutator_record() {
197+
if (!_active) {
198+
return;
199+
}
200+
_mutator_iowait_percent = _io_wait_record.stop();
201+
_mutator_user_percent = _user_time_record.stop();
202+
}
203+
204+
void print(double mutator_cost) const {
205+
if (!_active) {
206+
return;
207+
}
208+
if (PrintAdaptiveSizePolicy) {
209+
gclog_or_tty->print_cr("mutator cost: %f, iowait : %f, user: %f",
210+
mutator_cost, _mutator_iowait_percent,
211+
_mutator_user_percent);
212+
}
213+
}
214+
215+
bool should_full_GC() {
216+
if (!_active) {
217+
return false;
218+
}
219+
220+
// These thresholds are tuned by spark on TPC-DS workload.
221+
const static double IOTriggerredFullGCUserThreshold = 0.75;
222+
const static double IOTriggerredFullGCIOWaitThreshold = 0.4;
223+
const static double IOTriggerredFullGCMinInterval =
224+
60; // can be set longer if io heavy workload lasts long.
225+
226+
if (_mutator_user_percent < IOTriggerredFullGCUserThreshold &&
227+
_mutator_iowait_percent > IOTriggerredFullGCIOWaitThreshold) {
228+
_io_triggerred_major_gc_timer.stop();
229+
if (_io_triggerred_major_gc_timer.seconds() >
230+
IOTriggerredFullGCMinInterval) {
231+
_io_triggerred_major_gc_timer.reset();
232+
_io_triggerred_major_gc_timer.start();
233+
if (PrintAdaptiveSizePolicy) {
234+
gclog_or_tty->print_cr("decrease old gen by full gc");
235+
}
236+
return true;
237+
} else {
238+
if (PrintAdaptiveSizePolicy) {
239+
gclog_or_tty->print_cr(
240+
"decrease old gen FAILED because interval is %f < %f",
241+
_io_triggerred_major_gc_timer.seconds(),
242+
IOTriggerredFullGCMinInterval);
243+
}
244+
_io_triggerred_major_gc_timer.start();
245+
return false;
246+
}
247+
}
248+
return false;
249+
}
250+
251+
double calculate_reduced_throughput_goal() {
252+
if (!_active) {
253+
return _default_throughput_goal;
254+
}
255+
256+
const static double UserThreshold = 1.0;
257+
const static double IOWaitThreshold = 0.1;
258+
259+
if (_mutator_user_percent < UserThreshold &&
260+
_mutator_iowait_percent > IOWaitThreshold) {
261+
double reduced_throughput_goal = _default_throughput_goal - (1 - _mutator_user_percent);
262+
_should_reduce_heap = true;
263+
if (PrintAdaptiveSizePolicy) {
264+
gclog_or_tty->print_cr("decrease throughput goal to %.3f",
265+
reduced_throughput_goal);
266+
}
267+
return reduced_throughput_goal;
268+
} else {
269+
_should_reduce_heap = false;
270+
return _default_throughput_goal;
271+
}
272+
}
273+
274+
size_t calculate_reduced_eden_size(size_t eden_size, float avg_survivor, size_t current_eden_size) const {
275+
if (!_active || !_should_reduce_heap) {
276+
return eden_size;
277+
}
278+
size_t reduced_size;
279+
reduced_size = MIN(eden_size, avg_survivor * IOPrioritySizePolicyEdenScale);
280+
reduced_size = MAX(reduced_size, ParallelScavengeHeap::heap()->young_gen()->max_size() / 10);
281+
if (PrintAdaptiveSizePolicy) {
282+
gclog_or_tty->print_cr(
283+
"decrease eden from " SIZE_FORMAT "M to " SIZE_FORMAT
284+
"M , survivor avg: %fM, min threshold: " SIZE_FORMAT "M",
285+
current_eden_size / M, reduced_size / M, avg_survivor / M,
286+
ParallelScavengeHeap::heap()->young_gen()->max_size() / 10 / M);
287+
}
288+
return reduced_size;
289+
}
290+
291+
size_t calculate_reduced_promo_size(size_t promo_size, float avg_promo, size_t current_promo_size) const {
292+
if (!_active || !_should_reduce_heap) {
293+
return promo_size;
294+
}
295+
const static float PromoScale = 5;
296+
size_t reduced_size;
297+
reduced_size = MIN(reduced_size, avg_promo * PromoScale);
298+
reduced_size = MAX(reduced_size,
299+
ParallelScavengeHeap::heap()->old_gen()->max_gen_size() / 10);
300+
if (PrintAdaptiveSizePolicy) {
301+
gclog_or_tty->print_cr(
302+
"decrease promotion from " SIZE_FORMAT "M to " SIZE_FORMAT
303+
"M , promo avg: %fM, min threshold: " SIZE_FORMAT "M",
304+
current_promo_size / M, reduced_size / M, avg_promo / M,
305+
ParallelScavengeHeap::heap()->old_gen()->max_gen_size() / 10 / M);
306+
}
307+
return reduced_size;
308+
}
309+
};
310+
311+
40312
PSAdaptiveSizePolicy::PSAdaptiveSizePolicy(size_t init_eden_size,
41313
size_t init_promo_size,
42314
size_t init_survivor_size,
@@ -54,6 +326,7 @@ PSAdaptiveSizePolicy::PSAdaptiveSizePolicy(size_t init_eden_size,
54326
_live_at_last_full_gc(init_promo_size),
55327
_gc_minor_pause_goal_sec(gc_minor_pause_goal_sec),
56328
_latest_major_mutator_interval_seconds(0),
329+
_throughput_goal(AdaptiveSizePolicy::_throughput_goal),
57330
_young_gen_change_for_major_pause_count(0)
58331
{
59332
// Sizing policy statistics
@@ -77,6 +350,9 @@ PSAdaptiveSizePolicy::PSAdaptiveSizePolicy(size_t init_eden_size,
77350
_major_timer.start();
78351

79352
_old_gen_policy_is_ready = false;
353+
if (UseIOPrioritySizePolicy) {
354+
_io_policy = new IOPolicy(_throughput_goal);
355+
}
80356
}
81357

82358
size_t PSAdaptiveSizePolicy::calculate_free_based_on_live(size_t live, uintx ratio_as_percentage) {
@@ -111,6 +387,22 @@ size_t PSAdaptiveSizePolicy::calculated_old_free_size_in_bytes() const {
111387
return free_size;
112388
}
113389

390+
void PSAdaptiveSizePolicy::minor_collection_begin() {
391+
AdaptiveSizePolicy::minor_collection_begin();
392+
if (UseIOPrioritySizePolicy) {
393+
_io_policy->stop_mutator_record();
394+
}
395+
}
396+
397+
void PSAdaptiveSizePolicy::minor_collection_end(GCCause::Cause gc_cause) {
398+
AdaptiveSizePolicy::minor_collection_end(gc_cause);
399+
if (UseIOPrioritySizePolicy) {
400+
_io_policy->start_mutator_record();
401+
_io_policy->print(adjusted_mutator_cost());
402+
}
403+
}
404+
405+
114406
void PSAdaptiveSizePolicy::major_collection_begin() {
115407
// Update the interval time
116408
_major_timer.stop();
@@ -131,6 +423,9 @@ void PSAdaptiveSizePolicy::major_collection_end(size_t amount_live,
131423
GCCause::Cause gc_cause) {
132424
// Update the pause time.
133425
_major_timer.stop();
426+
if (UseIOPrioritySizePolicy) {
427+
_io_policy->start_mutator_record();
428+
}
134429

135430
if (gc_cause != GCCause::_java_lang_system_gc ||
136431
UseAdaptiveSizePolicyWithSystemGC) {
@@ -175,6 +470,10 @@ void PSAdaptiveSizePolicy::major_collection_end(size_t amount_live,
175470
assert(collection_cost >= 0.0, "Expected to be non-negative");
176471
_major_collection_estimator->update(promo_size_in_mbytes,
177472
collection_cost);
473+
474+
if (UseIOPrioritySizePolicy) {
475+
_io_policy->print(adjusted_mutator_cost());
476+
}
178477
}
179478

180479
// Update the amount live at the end of a full GC
@@ -196,6 +495,11 @@ void PSAdaptiveSizePolicy::major_collection_end(size_t amount_live,
196495
// that expected to be needed by the next collection, do a full
197496
// collection now.
198497
bool PSAdaptiveSizePolicy::should_full_GC(size_t old_free_in_bytes) {
498+
if (UseIOPrioritySizePolicy) {
499+
if (_io_policy->should_full_GC()) {
500+
return true;
501+
}
502+
}
199503

200504
// A similar test is done in the scavenge's should_attempt_scavenge(). If
201505
// this is changed, decide if that test should also be changed.
@@ -253,6 +557,9 @@ void PSAdaptiveSizePolicy::compute_eden_space_size(
253557
size_t cur_eden,
254558
size_t max_eden_size,
255559
bool is_full_gc) {
560+
if (UseIOPrioritySizePolicy) {
561+
_throughput_goal = _io_policy->calculate_reduced_throughput_goal();
562+
}
256563

257564
// Update statistics
258565
// Time statistics are updated as we go, update footprint stats here
@@ -1030,6 +1337,11 @@ size_t PSAdaptiveSizePolicy::adjust_promo_for_footprint(
10301337

10311338
size_t reduced_size = desired_promo_size - change;
10321339

1340+
if (UseIOPrioritySizePolicy) {
1341+
reduced_size = _io_policy->calculate_reduced_promo_size(reduced_size, avg_promoted()->average(), desired_promo_size);
1342+
change = desired_promo_size - reduced_size;
1343+
}
1344+
10331345
if (PrintAdaptiveSizePolicy && Verbose) {
10341346
gclog_or_tty->print_cr(
10351347
"AdaptiveSizePolicy::adjust_promo_for_footprint "
@@ -1054,6 +1366,11 @@ size_t PSAdaptiveSizePolicy::adjust_eden_for_footprint(
10541366

10551367
size_t reduced_size = desired_eden_size - change;
10561368

1369+
if (UseIOPrioritySizePolicy) {
1370+
reduced_size = _io_policy->calculate_reduced_eden_size(reduced_size, avg_survived()->average(), desired_eden_size);
1371+
change = desired_eden_size - reduced_size;
1372+
}
1373+
10571374
if (PrintAdaptiveSizePolicy && Verbose) {
10581375
gclog_or_tty->print_cr(
10591376
"AdaptiveSizePolicy::adjust_eden_for_footprint "

0 commit comments

Comments
 (0)