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