Mercurial > hg > truffle
annotate src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp @ 3772:6747fd0512e0
7004681: G1: Extend marking verification to Full GCs
Summary: Perform a heap verification after the first phase of G1's full GC using objects' mark words to determine liveness. The third parameter of the heap verification routines, which was used in G1 to determine which marking bitmap to use in liveness calculations, has been changed from a boolean to an enum with values defined for using the mark word, and the 'prev' and 'next' bitmaps.
Reviewed-by: tonyp, ysr
author | johnc |
---|---|
date | Tue, 14 Jun 2011 11:01:10 -0700 |
parents | f95d63e2154a |
children | da91efe96a93 |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1387
diff
changeset
|
2 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1387
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1387
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1387
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 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" | |
0 | 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 | |
1387
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
197 void PSAdaptiveSizePolicy::compute_generation_free_space( |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
198 size_t young_live, |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
199 size_t eden_live, |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
200 size_t old_live, |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
201 size_t perm_live, |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
202 size_t cur_eden, |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
203 size_t max_old_gen_size, |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
204 size_t max_eden_size, |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
205 bool is_full_gc, |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
206 GCCause::Cause gc_cause, |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
207 CollectorPolicy* collector_policy) { |
0 | 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 | |
1387
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
392 const size_t free_in_old_gen = |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
393 (size_t)(max_old_gen_size - avg_old_live()->average()); |
0 | 394 if (desired_promo_size > free_in_old_gen && desired_eden_size > eden_limit) { |
1387
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
395 check_gc_overhead_limit(young_live, |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
396 eden_live, |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
397 max_old_gen_size, |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
398 max_eden_size, |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
399 is_full_gc, |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
400 gc_cause, |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
0
diff
changeset
|
401 collector_policy); |
0 | 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 } |