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