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