Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp
41149 views
1
/*
2
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
#include "precompiled.hpp"
26
#include "gc/parallel/parallelScavengeHeap.hpp"
27
#include "gc/parallel/psAdaptiveSizePolicy.hpp"
28
#include "gc/parallel/psGCAdaptivePolicyCounters.hpp"
29
#include "gc/parallel/psScavenge.hpp"
30
#include "gc/shared/gcCause.hpp"
31
#include "gc/shared/gcUtil.inline.hpp"
32
#include "gc/shared/gcPolicyCounters.hpp"
33
#include "logging/log.hpp"
34
#include "runtime/timer.hpp"
35
#include "utilities/align.hpp"
36
37
#include <math.h>
38
39
PSAdaptiveSizePolicy::PSAdaptiveSizePolicy(size_t init_eden_size,
40
size_t init_promo_size,
41
size_t init_survivor_size,
42
size_t space_alignment,
43
double gc_pause_goal_sec,
44
double gc_minor_pause_goal_sec,
45
uint gc_cost_ratio) :
46
AdaptiveSizePolicy(init_eden_size,
47
init_promo_size,
48
init_survivor_size,
49
gc_pause_goal_sec,
50
gc_cost_ratio),
51
_avg_major_pause(new AdaptivePaddedAverage(AdaptiveTimeWeight, PausePadding)),
52
_avg_base_footprint(new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight)),
53
_gc_stats(),
54
_collection_cost_margin_fraction(AdaptiveSizePolicyCollectionCostMargin / 100.0),
55
_major_pause_old_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)),
56
_major_pause_young_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)),
57
_latest_major_mutator_interval_seconds(0),
58
_space_alignment(space_alignment),
59
_gc_minor_pause_goal_sec(gc_minor_pause_goal_sec),
60
_live_at_last_full_gc(init_promo_size),
61
_change_old_gen_for_min_pauses(0),
62
_change_young_gen_for_maj_pauses(0),
63
_young_gen_size_increment_supplement(YoungGenerationSizeSupplement),
64
_old_gen_size_increment_supplement(TenuredGenerationSizeSupplement)
65
{
66
// Start the timers
67
_major_timer.start();
68
}
69
70
size_t PSAdaptiveSizePolicy::calculate_free_based_on_live(size_t live, uintx ratio_as_percentage) {
71
// We want to calculate how much free memory there can be based on the
72
// amount of live data currently in the old gen. Using the formula:
73
// ratio * (free + live) = free
74
// Some equation solving later we get:
75
// free = (live * ratio) / (1 - ratio)
76
77
const double ratio = ratio_as_percentage / 100.0;
78
const double ratio_inverse = 1.0 - ratio;
79
const double tmp = live * ratio;
80
size_t free = (size_t)(tmp / ratio_inverse);
81
82
return free;
83
}
84
85
size_t PSAdaptiveSizePolicy::calculated_old_free_size_in_bytes() const {
86
size_t free_size = (size_t)(_promo_size + avg_promoted()->padded_average());
87
size_t live = ParallelScavengeHeap::heap()->old_gen()->used_in_bytes();
88
89
if (MinHeapFreeRatio != 0) {
90
size_t min_free = calculate_free_based_on_live(live, MinHeapFreeRatio);
91
free_size = MAX2(free_size, min_free);
92
}
93
94
if (MaxHeapFreeRatio != 100) {
95
size_t max_free = calculate_free_based_on_live(live, MaxHeapFreeRatio);
96
free_size = MIN2(max_free, free_size);
97
}
98
99
return free_size;
100
}
101
102
void PSAdaptiveSizePolicy::major_collection_begin() {
103
// Update the interval time
104
_major_timer.stop();
105
// Save most recent collection time
106
_latest_major_mutator_interval_seconds = _major_timer.seconds();
107
_major_timer.reset();
108
_major_timer.start();
109
}
110
111
void PSAdaptiveSizePolicy::update_minor_pause_old_estimator(
112
double minor_pause_in_ms) {
113
double promo_size_in_mbytes = ((double)_promo_size)/((double)M);
114
_minor_pause_old_estimator->update(promo_size_in_mbytes,
115
minor_pause_in_ms);
116
}
117
118
void PSAdaptiveSizePolicy::major_collection_end(size_t amount_live,
119
GCCause::Cause gc_cause) {
120
// Update the pause time.
121
_major_timer.stop();
122
123
if (should_update_promo_stats(gc_cause)) {
124
double major_pause_in_seconds = _major_timer.seconds();
125
double major_pause_in_ms = major_pause_in_seconds * MILLIUNITS;
126
127
// Sample for performance counter
128
_avg_major_pause->sample(major_pause_in_seconds);
129
130
// Cost of collection (unit-less)
131
double collection_cost = 0.0;
132
if ((_latest_major_mutator_interval_seconds > 0.0) &&
133
(major_pause_in_seconds > 0.0)) {
134
double interval_in_seconds =
135
_latest_major_mutator_interval_seconds + major_pause_in_seconds;
136
collection_cost =
137
major_pause_in_seconds / interval_in_seconds;
138
avg_major_gc_cost()->sample(collection_cost);
139
140
// Sample for performance counter
141
_avg_major_interval->sample(interval_in_seconds);
142
}
143
144
// Calculate variables used to estimate pause time vs. gen sizes
145
double eden_size_in_mbytes = ((double)_eden_size)/((double)M);
146
double promo_size_in_mbytes = ((double)_promo_size)/((double)M);
147
_major_pause_old_estimator->update(promo_size_in_mbytes,
148
major_pause_in_ms);
149
_major_pause_young_estimator->update(eden_size_in_mbytes,
150
major_pause_in_ms);
151
152
log_trace(gc, ergo)("psAdaptiveSizePolicy::major_collection_end: major gc cost: %f average: %f",
153
collection_cost,avg_major_gc_cost()->average());
154
log_trace(gc, ergo)(" major pause: %f major period %f",
155
major_pause_in_ms, _latest_major_mutator_interval_seconds * MILLIUNITS);
156
157
// Calculate variable used to estimate collection cost vs. gen sizes
158
assert(collection_cost >= 0.0, "Expected to be non-negative");
159
_major_collection_estimator->update(promo_size_in_mbytes,
160
collection_cost);
161
}
162
163
// Update the amount live at the end of a full GC
164
_live_at_last_full_gc = amount_live;
165
166
// Interval times use this timer to measure the interval that
167
// the mutator runs. Reset after the GC pause has been measured.
168
_major_timer.reset();
169
_major_timer.start();
170
}
171
172
// If the remaining free space in the old generation is less that
173
// that expected to be needed by the next collection, do a full
174
// collection now.
175
bool PSAdaptiveSizePolicy::should_full_GC(size_t old_free_in_bytes) {
176
177
// A similar test is done in the scavenge's should_attempt_scavenge(). If
178
// this is changed, decide if that test should also be changed.
179
bool result = padded_average_promoted_in_bytes() > (float) old_free_in_bytes;
180
log_trace(gc, ergo)("%s after scavenge average_promoted " SIZE_FORMAT " padded_average_promoted " SIZE_FORMAT " free in old gen " SIZE_FORMAT,
181
result ? "Full" : "No full",
182
(size_t) average_promoted_in_bytes(),
183
(size_t) padded_average_promoted_in_bytes(),
184
old_free_in_bytes);
185
return result;
186
}
187
188
void PSAdaptiveSizePolicy::clear_generation_free_space_flags() {
189
190
AdaptiveSizePolicy::clear_generation_free_space_flags();
191
192
set_change_old_gen_for_min_pauses(0);
193
194
set_change_young_gen_for_maj_pauses(0);
195
}
196
197
// If this is not a full GC, only test and modify the young generation.
198
199
void PSAdaptiveSizePolicy::compute_generations_free_space(
200
size_t young_live,
201
size_t eden_live,
202
size_t old_live,
203
size_t cur_eden,
204
size_t max_old_gen_size,
205
size_t max_eden_size,
206
bool is_full_gc) {
207
compute_eden_space_size(young_live,
208
eden_live,
209
cur_eden,
210
max_eden_size,
211
is_full_gc);
212
213
compute_old_gen_free_space(old_live,
214
cur_eden,
215
max_old_gen_size,
216
is_full_gc);
217
}
218
219
void PSAdaptiveSizePolicy::compute_eden_space_size(
220
size_t young_live,
221
size_t eden_live,
222
size_t cur_eden,
223
size_t max_eden_size,
224
bool is_full_gc) {
225
226
// Update statistics
227
// Time statistics are updated as we go, update footprint stats here
228
_avg_base_footprint->sample(BaseFootPrintEstimate);
229
avg_young_live()->sample(young_live);
230
avg_eden_live()->sample(eden_live);
231
232
// This code used to return if the policy was not ready , i.e.,
233
// policy_is_ready() returning false. The intent was that
234
// decisions below needed major collection times and so could
235
// not be made before two major collections. A consequence was
236
// adjustments to the young generation were not done until after
237
// two major collections even if the minor collections times
238
// exceeded the requested goals. Now let the young generation
239
// adjust for the minor collection times. Major collection times
240
// will be zero for the first collection and will naturally be
241
// ignored. Tenured generation adjustments are only made at the
242
// full collections so until the second major collection has
243
// been reached, no tenured generation adjustments will be made.
244
245
// Until we know better, desired promotion size uses the last calculation
246
size_t desired_promo_size = _promo_size;
247
248
// Start eden at the current value. The desired value that is stored
249
// in _eden_size is not bounded by constraints of the heap and can
250
// run away.
251
//
252
// As expected setting desired_eden_size to the current
253
// value of desired_eden_size as a starting point
254
// caused desired_eden_size to grow way too large and caused
255
// an overflow down stream. It may have improved performance in
256
// some case but is dangerous.
257
size_t desired_eden_size = cur_eden;
258
259
// Cache some values. There's a bit of work getting these, so
260
// we might save a little time.
261
const double major_cost = major_gc_cost();
262
const double minor_cost = minor_gc_cost();
263
264
// This method sets the desired eden size. That plus the
265
// desired survivor space sizes sets the desired young generation
266
// size. This methods does not know what the desired survivor
267
// size is but expects that other policy will attempt to make
268
// the survivor sizes compatible with the live data in the
269
// young generation. This limit is an estimate of the space left
270
// in the young generation after the survivor spaces have been
271
// subtracted out.
272
size_t eden_limit = max_eden_size;
273
274
const double gc_cost_limit = GCTimeLimit / 100.0;
275
276
// Which way should we go?
277
// if pause requirement is not met
278
// adjust size of any generation with average paus exceeding
279
// the pause limit. Adjust one pause at a time (the larger)
280
// and only make adjustments for the major pause at full collections.
281
// else if throughput requirement not met
282
// adjust the size of the generation with larger gc time. Only
283
// adjust one generation at a time.
284
// else
285
// adjust down the total heap size. Adjust down the larger of the
286
// generations.
287
288
// Add some checks for a threshold for a change. For example,
289
// a change less than the necessary alignment is probably not worth
290
// attempting.
291
292
293
if ((_avg_minor_pause->padded_average() > gc_pause_goal_sec()) ||
294
(_avg_major_pause->padded_average() > gc_pause_goal_sec())) {
295
//
296
// Check pauses
297
//
298
// Make changes only to affect one of the pauses (the larger)
299
// at a time.
300
adjust_eden_for_pause_time(is_full_gc, &desired_promo_size, &desired_eden_size);
301
302
} else if (_avg_minor_pause->padded_average() > gc_minor_pause_goal_sec()) {
303
// Adjust only for the minor pause time goal
304
adjust_eden_for_minor_pause_time(is_full_gc, &desired_eden_size);
305
306
} else if(adjusted_mutator_cost() < _throughput_goal) {
307
// This branch used to require that (mutator_cost() > 0.0 in 1.4.2.
308
// This sometimes resulted in skipping to the minimize footprint
309
// code. Change this to try and reduce GC time if mutator time is
310
// negative for whatever reason. Or for future consideration,
311
// bail out of the code if mutator time is negative.
312
//
313
// Throughput
314
//
315
assert(major_cost >= 0.0, "major cost is < 0.0");
316
assert(minor_cost >= 0.0, "minor cost is < 0.0");
317
// Try to reduce the GC times.
318
adjust_eden_for_throughput(is_full_gc, &desired_eden_size);
319
320
} else {
321
322
// Be conservative about reducing the footprint.
323
// Do a minimum number of major collections first.
324
// Have reasonable averages for major and minor collections costs.
325
if (UseAdaptiveSizePolicyFootprintGoal &&
326
young_gen_policy_is_ready() &&
327
avg_major_gc_cost()->average() >= 0.0 &&
328
avg_minor_gc_cost()->average() >= 0.0) {
329
size_t desired_sum = desired_eden_size + desired_promo_size;
330
desired_eden_size = adjust_eden_for_footprint(desired_eden_size, desired_sum);
331
}
332
}
333
334
// Note we make the same tests as in the code block below; the code
335
// seems a little easier to read with the printing in another block.
336
if (desired_eden_size > eden_limit) {
337
log_debug(gc, ergo)(
338
"PSAdaptiveSizePolicy::compute_eden_space_size limits:"
339
" desired_eden_size: " SIZE_FORMAT
340
" old_eden_size: " SIZE_FORMAT
341
" eden_limit: " SIZE_FORMAT
342
" cur_eden: " SIZE_FORMAT
343
" max_eden_size: " SIZE_FORMAT
344
" avg_young_live: " SIZE_FORMAT,
345
desired_eden_size, _eden_size, eden_limit, cur_eden,
346
max_eden_size, (size_t)avg_young_live()->average());
347
}
348
if (gc_cost() > gc_cost_limit) {
349
log_debug(gc, ergo)(
350
"PSAdaptiveSizePolicy::compute_eden_space_size: gc time limit"
351
" gc_cost: %f "
352
" GCTimeLimit: " UINTX_FORMAT,
353
gc_cost(), GCTimeLimit);
354
}
355
356
// Align everything and make a final limit check
357
desired_eden_size = align_up(desired_eden_size, _space_alignment);
358
desired_eden_size = MAX2(desired_eden_size, _space_alignment);
359
360
eden_limit = align_down(eden_limit, _space_alignment);
361
362
// And one last limit check, now that we've aligned things.
363
if (desired_eden_size > eden_limit) {
364
// If the policy says to get a larger eden but
365
// is hitting the limit, don't decrease eden.
366
// This can lead to a general drifting down of the
367
// eden size. Let the tenuring calculation push more
368
// into the old gen.
369
desired_eden_size = MAX2(eden_limit, cur_eden);
370
}
371
372
log_debug(gc, ergo)("PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: %f major_cost: %f mutator_cost: %f throughput_goal: %f",
373
minor_gc_cost(), major_gc_cost(), mutator_cost(), _throughput_goal);
374
375
log_trace(gc, ergo)("Minor_pause: %f major_pause: %f minor_interval: %f major_interval: %fpause_goal: %f",
376
_avg_minor_pause->padded_average(),
377
_avg_major_pause->padded_average(),
378
_avg_minor_interval->average(),
379
_avg_major_interval->average(),
380
gc_pause_goal_sec());
381
382
log_debug(gc, ergo)("Live_space: " SIZE_FORMAT " free_space: " SIZE_FORMAT,
383
live_space(), free_space());
384
385
log_trace(gc, ergo)("Base_footprint: " SIZE_FORMAT " avg_young_live: " SIZE_FORMAT " avg_old_live: " SIZE_FORMAT,
386
(size_t)_avg_base_footprint->average(),
387
(size_t)avg_young_live()->average(),
388
(size_t)avg_old_live()->average());
389
390
log_debug(gc, ergo)("Old eden_size: " SIZE_FORMAT " desired_eden_size: " SIZE_FORMAT,
391
_eden_size, desired_eden_size);
392
393
set_eden_size(desired_eden_size);
394
}
395
396
void PSAdaptiveSizePolicy::compute_old_gen_free_space(
397
size_t old_live,
398
size_t cur_eden,
399
size_t max_old_gen_size,
400
bool is_full_gc) {
401
402
// Update statistics
403
// Time statistics are updated as we go, update footprint stats here
404
if (is_full_gc) {
405
// old_live is only accurate after a full gc
406
avg_old_live()->sample(old_live);
407
}
408
409
// This code used to return if the policy was not ready , i.e.,
410
// policy_is_ready() returning false. The intent was that
411
// decisions below needed major collection times and so could
412
// not be made before two major collections. A consequence was
413
// adjustments to the young generation were not done until after
414
// two major collections even if the minor collections times
415
// exceeded the requested goals. Now let the young generation
416
// adjust for the minor collection times. Major collection times
417
// will be zero for the first collection and will naturally be
418
// ignored. Tenured generation adjustments are only made at the
419
// full collections so until the second major collection has
420
// been reached, no tenured generation adjustments will be made.
421
422
// Until we know better, desired promotion size uses the last calculation
423
size_t desired_promo_size = _promo_size;
424
425
// Start eden at the current value. The desired value that is stored
426
// in _eden_size is not bounded by constraints of the heap and can
427
// run away.
428
//
429
// As expected setting desired_eden_size to the current
430
// value of desired_eden_size as a starting point
431
// caused desired_eden_size to grow way too large and caused
432
// an overflow down stream. It may have improved performance in
433
// some case but is dangerous.
434
size_t desired_eden_size = cur_eden;
435
436
// Cache some values. There's a bit of work getting these, so
437
// we might save a little time.
438
const double major_cost = major_gc_cost();
439
const double minor_cost = minor_gc_cost();
440
441
// Limits on our growth
442
size_t promo_limit = (size_t)(max_old_gen_size - avg_old_live()->average());
443
444
// But don't force a promo size below the current promo size. Otherwise,
445
// the promo size will shrink for no good reason.
446
promo_limit = MAX2(promo_limit, _promo_size);
447
448
const double gc_cost_limit = GCTimeLimit/100.0;
449
450
// Which way should we go?
451
// if pause requirement is not met
452
// adjust size of any generation with average paus exceeding
453
// the pause limit. Adjust one pause at a time (the larger)
454
// and only make adjustments for the major pause at full collections.
455
// else if throughput requirement not met
456
// adjust the size of the generation with larger gc time. Only
457
// adjust one generation at a time.
458
// else
459
// adjust down the total heap size. Adjust down the larger of the
460
// generations.
461
462
// Add some checks for a threshold for a change. For example,
463
// a change less than the necessary alignment is probably not worth
464
// attempting.
465
466
if ((_avg_minor_pause->padded_average() > gc_pause_goal_sec()) ||
467
(_avg_major_pause->padded_average() > gc_pause_goal_sec())) {
468
//
469
// Check pauses
470
//
471
// Make changes only to affect one of the pauses (the larger)
472
// at a time.
473
if (is_full_gc) {
474
set_decide_at_full_gc(decide_at_full_gc_true);
475
adjust_promo_for_pause_time(is_full_gc, &desired_promo_size, &desired_eden_size);
476
}
477
} else if (adjusted_mutator_cost() < _throughput_goal) {
478
// This branch used to require that (mutator_cost() > 0.0 in 1.4.2.
479
// This sometimes resulted in skipping to the minimize footprint
480
// code. Change this to try and reduce GC time if mutator time is
481
// negative for whatever reason. Or for future consideration,
482
// bail out of the code if mutator time is negative.
483
//
484
// Throughput
485
//
486
assert(major_cost >= 0.0, "major cost is < 0.0");
487
assert(minor_cost >= 0.0, "minor cost is < 0.0");
488
// Try to reduce the GC times.
489
if (is_full_gc) {
490
set_decide_at_full_gc(decide_at_full_gc_true);
491
adjust_promo_for_throughput(is_full_gc, &desired_promo_size);
492
}
493
} else {
494
495
// Be conservative about reducing the footprint.
496
// Do a minimum number of major collections first.
497
// Have reasonable averages for major and minor collections costs.
498
if (UseAdaptiveSizePolicyFootprintGoal &&
499
young_gen_policy_is_ready() &&
500
avg_major_gc_cost()->average() >= 0.0 &&
501
avg_minor_gc_cost()->average() >= 0.0) {
502
if (is_full_gc) {
503
set_decide_at_full_gc(decide_at_full_gc_true);
504
size_t desired_sum = desired_eden_size + desired_promo_size;
505
desired_promo_size = adjust_promo_for_footprint(desired_promo_size, desired_sum);
506
}
507
}
508
}
509
510
// Note we make the same tests as in the code block below; the code
511
// seems a little easier to read with the printing in another block.
512
if (desired_promo_size > promo_limit) {
513
// "free_in_old_gen" was the original value for used for promo_limit
514
size_t free_in_old_gen = (size_t)(max_old_gen_size - avg_old_live()->average());
515
log_debug(gc, ergo)(
516
"PSAdaptiveSizePolicy::compute_old_gen_free_space limits:"
517
" desired_promo_size: " SIZE_FORMAT
518
" promo_limit: " SIZE_FORMAT
519
" free_in_old_gen: " SIZE_FORMAT
520
" max_old_gen_size: " SIZE_FORMAT
521
" avg_old_live: " SIZE_FORMAT,
522
desired_promo_size, promo_limit, free_in_old_gen,
523
max_old_gen_size, (size_t) avg_old_live()->average());
524
}
525
if (gc_cost() > gc_cost_limit) {
526
log_debug(gc, ergo)(
527
"PSAdaptiveSizePolicy::compute_old_gen_free_space: gc time limit"
528
" gc_cost: %f "
529
" GCTimeLimit: " UINTX_FORMAT,
530
gc_cost(), GCTimeLimit);
531
}
532
533
// Align everything and make a final limit check
534
desired_promo_size = align_up(desired_promo_size, _space_alignment);
535
desired_promo_size = MAX2(desired_promo_size, _space_alignment);
536
537
promo_limit = align_down(promo_limit, _space_alignment);
538
539
// And one last limit check, now that we've aligned things.
540
desired_promo_size = MIN2(desired_promo_size, promo_limit);
541
542
// Timing stats
543
log_debug(gc, ergo)("PSAdaptiveSizePolicy::compute_old_gen_free_space: costs minor_time: %f major_cost: %f mutator_cost: %f throughput_goal: %f",
544
minor_gc_cost(), major_gc_cost(), mutator_cost(), _throughput_goal);
545
546
log_trace(gc, ergo)("Minor_pause: %f major_pause: %f minor_interval: %f major_interval: %f pause_goal: %f",
547
_avg_minor_pause->padded_average(),
548
_avg_major_pause->padded_average(),
549
_avg_minor_interval->average(),
550
_avg_major_interval->average(),
551
gc_pause_goal_sec());
552
553
// Footprint stats
554
log_debug(gc, ergo)("Live_space: " SIZE_FORMAT " free_space: " SIZE_FORMAT,
555
live_space(), free_space());
556
557
log_trace(gc, ergo)("Base_footprint: " SIZE_FORMAT " avg_young_live: " SIZE_FORMAT " avg_old_live: " SIZE_FORMAT,
558
(size_t)_avg_base_footprint->average(),
559
(size_t)avg_young_live()->average(),
560
(size_t)avg_old_live()->average());
561
562
log_debug(gc, ergo)("Old promo_size: " SIZE_FORMAT " desired_promo_size: " SIZE_FORMAT,
563
_promo_size, desired_promo_size);
564
565
set_promo_size(desired_promo_size);
566
}
567
568
void PSAdaptiveSizePolicy::decay_supplemental_growth(bool is_full_gc) {
569
// Decay the supplemental increment? Decay the supplement growth
570
// factor even if it is not used. It is only meant to give a boost
571
// to the initial growth and if it is not used, then it was not
572
// needed.
573
if (is_full_gc) {
574
// Don't wait for the threshold value for the major collections. If
575
// here, the supplemental growth term was used and should decay.
576
if ((_avg_major_pause->count() % TenuredGenerationSizeSupplementDecay)
577
== 0) {
578
_old_gen_size_increment_supplement =
579
_old_gen_size_increment_supplement >> 1;
580
}
581
} else {
582
if ((_avg_minor_pause->count() >= AdaptiveSizePolicyReadyThreshold) &&
583
(_avg_minor_pause->count() % YoungGenerationSizeSupplementDecay) == 0) {
584
_young_gen_size_increment_supplement =
585
_young_gen_size_increment_supplement >> 1;
586
}
587
}
588
}
589
590
void PSAdaptiveSizePolicy::adjust_eden_for_minor_pause_time(bool is_full_gc,
591
size_t* desired_eden_size_ptr) {
592
593
// Adjust the young generation size to reduce pause time of
594
// of collections.
595
//
596
// The AdaptiveSizePolicyInitializingSteps test is not used
597
// here. It has not seemed to be needed but perhaps should
598
// be added for consistency.
599
if (minor_pause_young_estimator()->decrement_will_decrease()) {
600
// reduce eden size
601
set_change_young_gen_for_min_pauses(
602
decrease_young_gen_for_min_pauses_true);
603
*desired_eden_size_ptr = *desired_eden_size_ptr -
604
eden_decrement_aligned_down(*desired_eden_size_ptr);
605
} else {
606
// EXPERIMENTAL ADJUSTMENT
607
// Only record that the estimator indicated such an action.
608
// *desired_eden_size_ptr = *desired_eden_size_ptr + eden_heap_delta;
609
set_change_young_gen_for_min_pauses(
610
increase_young_gen_for_min_pauses_true);
611
}
612
}
613
614
void PSAdaptiveSizePolicy::adjust_promo_for_pause_time(bool is_full_gc,
615
size_t* desired_promo_size_ptr,
616
size_t* desired_eden_size_ptr) {
617
618
size_t promo_heap_delta = 0;
619
// Add some checks for a threshold for a change. For example,
620
// a change less than the required alignment is probably not worth
621
// attempting.
622
623
if (_avg_minor_pause->padded_average() <= _avg_major_pause->padded_average() && is_full_gc) {
624
// Adjust for the major pause time only at full gc's because the
625
// affects of a change can only be seen at full gc's.
626
627
// Reduce old generation size to reduce pause?
628
if (major_pause_old_estimator()->decrement_will_decrease()) {
629
// reduce old generation size
630
set_change_old_gen_for_maj_pauses(decrease_old_gen_for_maj_pauses_true);
631
promo_heap_delta = promo_decrement_aligned_down(*desired_promo_size_ptr);
632
*desired_promo_size_ptr = _promo_size - promo_heap_delta;
633
} else {
634
// EXPERIMENTAL ADJUSTMENT
635
// Only record that the estimator indicated such an action.
636
// *desired_promo_size_ptr = _promo_size +
637
// promo_increment_aligned_up(*desired_promo_size_ptr);
638
set_change_old_gen_for_maj_pauses(increase_old_gen_for_maj_pauses_true);
639
}
640
}
641
642
log_trace(gc, ergo)(
643
"PSAdaptiveSizePolicy::adjust_promo_for_pause_time "
644
"adjusting gen sizes for major pause (avg %f goal %f). "
645
"desired_promo_size " SIZE_FORMAT " promo delta " SIZE_FORMAT,
646
_avg_major_pause->average(), gc_pause_goal_sec(),
647
*desired_promo_size_ptr, promo_heap_delta);
648
}
649
650
void PSAdaptiveSizePolicy::adjust_eden_for_pause_time(bool is_full_gc,
651
size_t* desired_promo_size_ptr,
652
size_t* desired_eden_size_ptr) {
653
654
size_t eden_heap_delta = 0;
655
// Add some checks for a threshold for a change. For example,
656
// a change less than the required alignment is probably not worth
657
// attempting.
658
if (_avg_minor_pause->padded_average() > _avg_major_pause->padded_average()) {
659
adjust_eden_for_minor_pause_time(is_full_gc, desired_eden_size_ptr);
660
}
661
log_trace(gc, ergo)(
662
"PSAdaptiveSizePolicy::adjust_eden_for_pause_time "
663
"adjusting gen sizes for major pause (avg %f goal %f). "
664
"desired_eden_size " SIZE_FORMAT " eden delta " SIZE_FORMAT,
665
_avg_major_pause->average(), gc_pause_goal_sec(),
666
*desired_eden_size_ptr, eden_heap_delta);
667
}
668
669
void PSAdaptiveSizePolicy::adjust_promo_for_throughput(bool is_full_gc,
670
size_t* desired_promo_size_ptr) {
671
672
// Add some checks for a threshold for a change. For example,
673
// a change less than the required alignment is probably not worth
674
// attempting.
675
676
if ((gc_cost() + mutator_cost()) == 0.0) {
677
return;
678
}
679
680
log_trace(gc, ergo)("PSAdaptiveSizePolicy::adjust_promo_for_throughput(is_full: %d, promo: " SIZE_FORMAT "): mutator_cost %f major_gc_cost %f minor_gc_cost %f",
681
is_full_gc, *desired_promo_size_ptr, mutator_cost(), major_gc_cost(), minor_gc_cost());
682
683
// Tenured generation
684
if (is_full_gc) {
685
// Calculate the change to use for the tenured gen.
686
size_t scaled_promo_heap_delta = 0;
687
// Can the increment to the generation be scaled?
688
if (gc_cost() >= 0.0 && major_gc_cost() >= 0.0) {
689
size_t promo_heap_delta =
690
promo_increment_with_supplement_aligned_up(*desired_promo_size_ptr);
691
double scale_by_ratio = major_gc_cost() / gc_cost();
692
scaled_promo_heap_delta =
693
(size_t) (scale_by_ratio * (double) promo_heap_delta);
694
log_trace(gc, ergo)("Scaled tenured increment: " SIZE_FORMAT " by %f down to " SIZE_FORMAT,
695
promo_heap_delta, scale_by_ratio, scaled_promo_heap_delta);
696
} else if (major_gc_cost() >= 0.0) {
697
// Scaling is not going to work. If the major gc time is the
698
// larger, give it a full increment.
699
if (major_gc_cost() >= minor_gc_cost()) {
700
scaled_promo_heap_delta =
701
promo_increment_with_supplement_aligned_up(*desired_promo_size_ptr);
702
}
703
} else {
704
// Don't expect to get here but it's ok if it does
705
// in the product build since the delta will be 0
706
// and nothing will change.
707
assert(false, "Unexpected value for gc costs");
708
}
709
710
switch (AdaptiveSizeThroughPutPolicy) {
711
case 1:
712
// Early in the run the statistics might not be good. Until
713
// a specific number of collections have been, use the heuristic
714
// that a larger generation size means lower collection costs.
715
if (major_collection_estimator()->increment_will_decrease() ||
716
(_old_gen_change_for_major_throughput
717
<= AdaptiveSizePolicyInitializingSteps)) {
718
// Increase tenured generation size to reduce major collection cost
719
if ((*desired_promo_size_ptr + scaled_promo_heap_delta) >
720
*desired_promo_size_ptr) {
721
*desired_promo_size_ptr = _promo_size + scaled_promo_heap_delta;
722
}
723
set_change_old_gen_for_throughput(
724
increase_old_gen_for_throughput_true);
725
_old_gen_change_for_major_throughput++;
726
} else {
727
// EXPERIMENTAL ADJUSTMENT
728
// Record that decreasing the old gen size would decrease
729
// the major collection cost but don't do it.
730
// *desired_promo_size_ptr = _promo_size -
731
// promo_decrement_aligned_down(*desired_promo_size_ptr);
732
set_change_old_gen_for_throughput(
733
decrease_old_gen_for_throughput_true);
734
}
735
736
break;
737
default:
738
// Simplest strategy
739
if ((*desired_promo_size_ptr + scaled_promo_heap_delta) >
740
*desired_promo_size_ptr) {
741
*desired_promo_size_ptr = *desired_promo_size_ptr +
742
scaled_promo_heap_delta;
743
}
744
set_change_old_gen_for_throughput(
745
increase_old_gen_for_throughput_true);
746
_old_gen_change_for_major_throughput++;
747
}
748
749
log_trace(gc, ergo)("Adjusting tenured gen for throughput (avg %f goal %f). desired_promo_size " SIZE_FORMAT " promo_delta " SIZE_FORMAT ,
750
mutator_cost(),
751
_throughput_goal,
752
*desired_promo_size_ptr, scaled_promo_heap_delta);
753
}
754
}
755
756
void PSAdaptiveSizePolicy::adjust_eden_for_throughput(bool is_full_gc,
757
size_t* desired_eden_size_ptr) {
758
759
// Add some checks for a threshold for a change. For example,
760
// a change less than the required alignment is probably not worth
761
// attempting.
762
763
if ((gc_cost() + mutator_cost()) == 0.0) {
764
return;
765
}
766
767
log_trace(gc, ergo)("PSAdaptiveSizePolicy::adjust_eden_for_throughput(is_full: %d, cur_eden: " SIZE_FORMAT "): mutator_cost %f major_gc_cost %f minor_gc_cost %f",
768
is_full_gc, *desired_eden_size_ptr, mutator_cost(), major_gc_cost(), minor_gc_cost());
769
770
// Young generation
771
size_t scaled_eden_heap_delta = 0;
772
// Can the increment to the generation be scaled?
773
if (gc_cost() >= 0.0 && minor_gc_cost() >= 0.0) {
774
size_t eden_heap_delta =
775
eden_increment_with_supplement_aligned_up(*desired_eden_size_ptr);
776
double scale_by_ratio = minor_gc_cost() / gc_cost();
777
assert(scale_by_ratio <= 1.0 && scale_by_ratio >= 0.0, "Scaling is wrong");
778
scaled_eden_heap_delta =
779
(size_t) (scale_by_ratio * (double) eden_heap_delta);
780
log_trace(gc, ergo)("Scaled eden increment: " SIZE_FORMAT " by %f down to " SIZE_FORMAT,
781
eden_heap_delta, scale_by_ratio, scaled_eden_heap_delta);
782
} else if (minor_gc_cost() >= 0.0) {
783
// Scaling is not going to work. If the minor gc time is the
784
// larger, give it a full increment.
785
if (minor_gc_cost() > major_gc_cost()) {
786
scaled_eden_heap_delta =
787
eden_increment_with_supplement_aligned_up(*desired_eden_size_ptr);
788
}
789
} else {
790
// Don't expect to get here but it's ok if it does
791
// in the product build since the delta will be 0
792
// and nothing will change.
793
assert(false, "Unexpected value for gc costs");
794
}
795
796
// Use a heuristic for some number of collections to give
797
// the averages time to settle down.
798
switch (AdaptiveSizeThroughPutPolicy) {
799
case 1:
800
if (minor_collection_estimator()->increment_will_decrease() ||
801
(_young_gen_change_for_minor_throughput
802
<= AdaptiveSizePolicyInitializingSteps)) {
803
// Expand young generation size to reduce frequency of
804
// of collections.
805
if ((*desired_eden_size_ptr + scaled_eden_heap_delta) >
806
*desired_eden_size_ptr) {
807
*desired_eden_size_ptr =
808
*desired_eden_size_ptr + scaled_eden_heap_delta;
809
}
810
set_change_young_gen_for_throughput(
811
increase_young_gen_for_througput_true);
812
_young_gen_change_for_minor_throughput++;
813
} else {
814
// EXPERIMENTAL ADJUSTMENT
815
// Record that decreasing the young gen size would decrease
816
// the minor collection cost but don't do it.
817
// *desired_eden_size_ptr = _eden_size -
818
// eden_decrement_aligned_down(*desired_eden_size_ptr);
819
set_change_young_gen_for_throughput(
820
decrease_young_gen_for_througput_true);
821
}
822
break;
823
default:
824
if ((*desired_eden_size_ptr + scaled_eden_heap_delta) >
825
*desired_eden_size_ptr) {
826
*desired_eden_size_ptr =
827
*desired_eden_size_ptr + scaled_eden_heap_delta;
828
}
829
set_change_young_gen_for_throughput(
830
increase_young_gen_for_througput_true);
831
_young_gen_change_for_minor_throughput++;
832
}
833
834
log_trace(gc, ergo)("Adjusting eden for throughput (avg %f goal %f). desired_eden_size " SIZE_FORMAT " eden delta " SIZE_FORMAT,
835
mutator_cost(), _throughput_goal, *desired_eden_size_ptr, scaled_eden_heap_delta);
836
}
837
838
size_t PSAdaptiveSizePolicy::adjust_promo_for_footprint(
839
size_t desired_promo_size, size_t desired_sum) {
840
assert(desired_promo_size <= desired_sum, "Inconsistent parameters");
841
set_decrease_for_footprint(decrease_old_gen_for_footprint_true);
842
843
size_t change = promo_decrement(desired_promo_size);
844
change = scale_down(change, desired_promo_size, desired_sum);
845
846
size_t reduced_size = desired_promo_size - change;
847
848
log_trace(gc, ergo)(
849
"AdaptiveSizePolicy::adjust_promo_for_footprint "
850
"adjusting tenured gen for footprint. "
851
"starting promo size " SIZE_FORMAT
852
" reduced promo size " SIZE_FORMAT
853
" promo delta " SIZE_FORMAT,
854
desired_promo_size, reduced_size, change );
855
856
assert(reduced_size <= desired_promo_size, "Inconsistent result");
857
return reduced_size;
858
}
859
860
size_t PSAdaptiveSizePolicy::adjust_eden_for_footprint(
861
size_t desired_eden_size, size_t desired_sum) {
862
assert(desired_eden_size <= desired_sum, "Inconsistent parameters");
863
set_decrease_for_footprint(decrease_young_gen_for_footprint_true);
864
865
size_t change = eden_decrement(desired_eden_size);
866
change = scale_down(change, desired_eden_size, desired_sum);
867
868
size_t reduced_size = desired_eden_size - change;
869
870
log_trace(gc, ergo)(
871
"AdaptiveSizePolicy::adjust_eden_for_footprint "
872
"adjusting eden for footprint. "
873
" starting eden size " SIZE_FORMAT
874
" reduced eden size " SIZE_FORMAT
875
" eden delta " SIZE_FORMAT,
876
desired_eden_size, reduced_size, change);
877
878
assert(reduced_size <= desired_eden_size, "Inconsistent result");
879
return reduced_size;
880
}
881
882
// Scale down "change" by the factor
883
// part / total
884
// Don't align the results.
885
886
size_t PSAdaptiveSizePolicy::scale_down(size_t change,
887
double part,
888
double total) {
889
assert(part <= total, "Inconsistent input");
890
size_t reduced_change = change;
891
if (total > 0) {
892
double fraction = part / total;
893
reduced_change = (size_t) (fraction * (double) change);
894
}
895
assert(reduced_change <= change, "Inconsistent result");
896
return reduced_change;
897
}
898
899
size_t PSAdaptiveSizePolicy::eden_increment(size_t cur_eden,
900
uint percent_change) {
901
size_t eden_heap_delta;
902
eden_heap_delta = cur_eden / 100 * percent_change;
903
return eden_heap_delta;
904
}
905
906
size_t PSAdaptiveSizePolicy::eden_increment(size_t cur_eden) {
907
return eden_increment(cur_eden, YoungGenerationSizeIncrement);
908
}
909
910
size_t PSAdaptiveSizePolicy::eden_increment_with_supplement_aligned_up(
911
size_t cur_eden) {
912
size_t result = eden_increment(cur_eden,
913
YoungGenerationSizeIncrement + _young_gen_size_increment_supplement);
914
return align_up(result, _space_alignment);
915
}
916
917
size_t PSAdaptiveSizePolicy::eden_decrement_aligned_down(size_t cur_eden) {
918
size_t eden_heap_delta = eden_decrement(cur_eden);
919
return align_down(eden_heap_delta, _space_alignment);
920
}
921
922
size_t PSAdaptiveSizePolicy::eden_decrement(size_t cur_eden) {
923
size_t eden_heap_delta = eden_increment(cur_eden) /
924
AdaptiveSizeDecrementScaleFactor;
925
return eden_heap_delta;
926
}
927
928
size_t PSAdaptiveSizePolicy::promo_increment(size_t cur_promo,
929
uint percent_change) {
930
size_t promo_heap_delta;
931
promo_heap_delta = cur_promo / 100 * percent_change;
932
return promo_heap_delta;
933
}
934
935
size_t PSAdaptiveSizePolicy::promo_increment(size_t cur_promo) {
936
return promo_increment(cur_promo, TenuredGenerationSizeIncrement);
937
}
938
939
size_t PSAdaptiveSizePolicy::promo_increment_with_supplement_aligned_up(
940
size_t cur_promo) {
941
size_t result = promo_increment(cur_promo,
942
TenuredGenerationSizeIncrement + _old_gen_size_increment_supplement);
943
return align_up(result, _space_alignment);
944
}
945
946
size_t PSAdaptiveSizePolicy::promo_decrement_aligned_down(size_t cur_promo) {
947
size_t promo_heap_delta = promo_decrement(cur_promo);
948
return align_down(promo_heap_delta, _space_alignment);
949
}
950
951
size_t PSAdaptiveSizePolicy::promo_decrement(size_t cur_promo) {
952
size_t promo_heap_delta = promo_increment(cur_promo);
953
promo_heap_delta = promo_heap_delta / AdaptiveSizeDecrementScaleFactor;
954
return promo_heap_delta;
955
}
956
957
uint PSAdaptiveSizePolicy::compute_survivor_space_size_and_threshold(
958
bool is_survivor_overflow,
959
uint tenuring_threshold,
960
size_t survivor_limit) {
961
assert(survivor_limit >= _space_alignment,
962
"survivor_limit too small");
963
assert(is_aligned(survivor_limit, _space_alignment),
964
"survivor_limit not aligned");
965
966
// This method is called even if the tenuring threshold and survivor
967
// spaces are not adjusted so that the averages are sampled above.
968
if (!UsePSAdaptiveSurvivorSizePolicy ||
969
!young_gen_policy_is_ready()) {
970
return tenuring_threshold;
971
}
972
973
// We'll decide whether to increase or decrease the tenuring
974
// threshold based partly on the newly computed survivor size
975
// (if we hit the maximum limit allowed, we'll always choose to
976
// decrement the threshold).
977
bool incr_tenuring_threshold = false;
978
bool decr_tenuring_threshold = false;
979
980
set_decrement_tenuring_threshold_for_gc_cost(false);
981
set_increment_tenuring_threshold_for_gc_cost(false);
982
set_decrement_tenuring_threshold_for_survivor_limit(false);
983
984
if (!is_survivor_overflow) {
985
// Keep running averages on how much survived
986
987
// We use the tenuring threshold to equalize the cost of major
988
// and minor collections.
989
// ThresholdTolerance is used to indicate how sensitive the
990
// tenuring threshold is to differences in cost between the
991
// collection types.
992
993
// Get the times of interest. This involves a little work, so
994
// we cache the values here.
995
const double major_cost = major_gc_cost();
996
const double minor_cost = minor_gc_cost();
997
998
if (minor_cost > major_cost * _threshold_tolerance_percent) {
999
// Minor times are getting too long; lower the threshold so
1000
// less survives and more is promoted.
1001
decr_tenuring_threshold = true;
1002
set_decrement_tenuring_threshold_for_gc_cost(true);
1003
} else if (major_cost > minor_cost * _threshold_tolerance_percent) {
1004
// Major times are too long, so we want less promotion.
1005
incr_tenuring_threshold = true;
1006
set_increment_tenuring_threshold_for_gc_cost(true);
1007
}
1008
1009
} else {
1010
// Survivor space overflow occurred, so promoted and survived are
1011
// not accurate. We'll make our best guess by combining survived
1012
// and promoted and count them as survivors.
1013
//
1014
// We'll lower the tenuring threshold to see if we can correct
1015
// things. Also, set the survivor size conservatively. We're
1016
// trying to avoid many overflows from occurring if defnew size
1017
// is just too small.
1018
1019
decr_tenuring_threshold = true;
1020
}
1021
1022
// The padded average also maintains a deviation from the average;
1023
// we use this to see how good of an estimate we have of what survived.
1024
// We're trying to pad the survivor size as little as possible without
1025
// overflowing the survivor spaces.
1026
size_t target_size = align_up((size_t)_avg_survived->padded_average(),
1027
_space_alignment);
1028
target_size = MAX2(target_size, _space_alignment);
1029
1030
if (target_size > survivor_limit) {
1031
// Target size is bigger than we can handle. Let's also reduce
1032
// the tenuring threshold.
1033
target_size = survivor_limit;
1034
decr_tenuring_threshold = true;
1035
set_decrement_tenuring_threshold_for_survivor_limit(true);
1036
}
1037
1038
// Finally, increment or decrement the tenuring threshold, as decided above.
1039
// We test for decrementing first, as we might have hit the target size
1040
// limit.
1041
if (decr_tenuring_threshold && !(AlwaysTenure || NeverTenure)) {
1042
if (tenuring_threshold > 1) {
1043
tenuring_threshold--;
1044
}
1045
} else if (incr_tenuring_threshold && !(AlwaysTenure || NeverTenure)) {
1046
if (tenuring_threshold < MaxTenuringThreshold) {
1047
tenuring_threshold++;
1048
}
1049
}
1050
1051
// We keep a running average of the amount promoted which is used
1052
// to decide when we should collect the old generation (when
1053
// the amount of old gen free space is less than what we expect to
1054
// promote).
1055
1056
log_trace(gc, ergo)("avg_survived: %f avg_deviation: %f", _avg_survived->average(), _avg_survived->deviation());
1057
log_debug(gc, ergo)("avg_survived_padded_avg: %f", _avg_survived->padded_average());
1058
1059
log_trace(gc, ergo)("avg_promoted_avg: %f avg_promoted_dev: %f", avg_promoted()->average(), avg_promoted()->deviation());
1060
log_debug(gc, ergo)("avg_promoted_padded_avg: %f avg_pretenured_padded_avg: %f tenuring_thresh: %d target_size: " SIZE_FORMAT,
1061
avg_promoted()->padded_average(),
1062
_avg_pretenured->padded_average(),
1063
tenuring_threshold, target_size);
1064
1065
set_survivor_size(target_size);
1066
1067
return tenuring_threshold;
1068
}
1069
1070
void PSAdaptiveSizePolicy::update_averages(bool is_survivor_overflow,
1071
size_t survived,
1072
size_t promoted) {
1073
// Update averages
1074
if (!is_survivor_overflow) {
1075
// Keep running averages on how much survived
1076
_avg_survived->sample(survived);
1077
} else {
1078
size_t survived_guess = survived + promoted;
1079
_avg_survived->sample(survived_guess);
1080
}
1081
avg_promoted()->sample(promoted);
1082
1083
log_trace(gc, ergo)("AdaptiveSizePolicy::update_averages: survived: " SIZE_FORMAT " promoted: " SIZE_FORMAT " overflow: %s",
1084
survived, promoted, is_survivor_overflow ? "true" : "false");
1085
}
1086
1087
bool PSAdaptiveSizePolicy::print() const {
1088
1089
if (!UseAdaptiveSizePolicy) {
1090
return false;
1091
}
1092
1093
if (AdaptiveSizePolicy::print()) {
1094
AdaptiveSizePolicy::print_tenuring_threshold(PSScavenge::tenuring_threshold());
1095
return true;
1096
}
1097
1098
return false;
1099
}
1100
1101