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