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/shared/adaptiveSizePolicy.hpp"
27 #include "gc/shared/gcCause.hpp"
28 #include "gc/shared/gcUtil.inline.hpp"
29 #include "gc/shared/softRefPolicy.hpp"
30 #include "logging/log.hpp"
31 #include "runtime/timer.hpp"
32
33 elapsedTimer AdaptiveSizePolicy::_minor_timer;
34 elapsedTimer AdaptiveSizePolicy::_major_timer;
35
36 // The throughput goal is implemented as
37 // _throughput_goal = 1 - ( 1 / (1 + gc_cost_ratio))
38 // gc_cost_ratio is the ratio
39 // application cost / gc cost
40 // For example a gc_cost_ratio of 4 translates into a
41 // throughput goal of .80
42
43 AdaptiveSizePolicy::AdaptiveSizePolicy(size_t init_eden_size,
44 size_t init_promo_size,
45 size_t init_survivor_size,
46 double gc_pause_goal_sec,
47 uint gc_cost_ratio) :
48 _throughput_goal(1.0 - double(1.0 / (1.0 + (double) gc_cost_ratio))),
49 _eden_size(init_eden_size),
50 _promo_size(init_promo_size),
51 _survivor_size(init_survivor_size),
52 _gc_overhead_limit_exceeded(false),
53 _print_gc_overhead_limit_would_be_exceeded(false),
54 _gc_overhead_limit_count(0),
55 _latest_minor_mutator_interval_seconds(0),
56 _threshold_tolerance_percent(1.0 + ThresholdTolerance/100.0),
57 _gc_pause_goal_sec(gc_pause_goal_sec),
58 _young_gen_change_for_minor_throughput(0),
59 _old_gen_change_for_major_throughput(0) {
60 assert(AdaptiveSizePolicyGCTimeLimitThreshold > 0,
61 "No opportunity to clear SoftReferences before GC overhead limit");
62 _avg_minor_pause =
63 new AdaptivePaddedAverage(AdaptiveTimeWeight, PausePadding);
64 _avg_minor_interval = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
65 _avg_minor_gc_cost = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
66 _avg_major_gc_cost = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
67
68 _avg_young_live = new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight);
69 _avg_old_live = new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight);
70 _avg_eden_live = new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight);
71
72 _avg_survived = new AdaptivePaddedAverage(AdaptiveSizePolicyWeight,
73 SurvivorPadding);
74 _avg_pretenured = new AdaptivePaddedNoZeroDevAverage(
75 AdaptiveSizePolicyWeight,
76 SurvivorPadding);
77
78 _minor_pause_old_estimator =
79 new LinearLeastSquareFit(AdaptiveSizePolicyWeight);
80 _minor_pause_young_estimator =
81 new LinearLeastSquareFit(AdaptiveSizePolicyWeight);
260 avg_major_interval, time_since_last_major_gc);
261 log_trace(gc, ergo)(" major gc cost: %f decayed major gc cost: %f",
262 major_gc_cost(), decayed_major_gc_cost);
263 }
264 }
265 double result = MIN2(1.0, decayed_major_gc_cost + minor_gc_cost());
266 return result;
267 }
268
269
270 void AdaptiveSizePolicy::clear_generation_free_space_flags() {
271 set_change_young_gen_for_min_pauses(0);
272 set_change_old_gen_for_maj_pauses(0);
273
274 set_change_old_gen_for_throughput(0);
275 set_change_young_gen_for_throughput(0);
276 set_decrease_for_footprint(0);
277 set_decide_at_full_gc(0);
278 }
279
280 void AdaptiveSizePolicy::check_gc_overhead_limit(
281 size_t young_live,
282 size_t eden_live,
283 size_t max_old_gen_size,
284 size_t max_eden_size,
285 bool is_full_gc,
286 GCCause::Cause gc_cause,
287 SoftRefPolicy* soft_ref_policy) {
288
289 // Ignore explicit GC's. Exiting here does not set the flag and
290 // does not reset the count. Updating of the averages for system
291 // GC's is still controlled by UseAdaptiveSizePolicyWithSystemGC.
292 if (GCCause::is_user_requested_gc(gc_cause) ||
293 GCCause::is_serviceability_requested_gc(gc_cause)) {
294 return;
295 }
296 // eden_limit is the upper limit on the size of eden based on
297 // the maximum size of the young generation and the sizes
298 // of the survivor space.
299 // The question being asked is whether the gc costs are high
300 // and the space being recovered by a collection is low.
301 // free_in_young_gen is the free space in the young generation
302 // after a collection and promo_live is the free space in the old
303 // generation after a collection.
304 //
305 // Use the minimum of the current value of the live in the
306 // young gen or the average of the live in the young gen.
307 // If the current value drops quickly, that should be taken
308 // into account (i.e., don't trigger if the amount of free
309 // space has suddenly jumped up). If the current is much
310 // higher than the average, use the average since it represents
311 // the longer term behavior.
312 const size_t live_in_eden =
313 MIN2(eden_live, (size_t) avg_eden_live()->average());
314 const size_t free_in_eden = max_eden_size > live_in_eden ?
315 max_eden_size - live_in_eden : 0;
316 const size_t free_in_old_gen = (size_t)(max_old_gen_size - avg_old_live()->average());
317 const size_t total_free_limit = free_in_old_gen + free_in_eden;
318 const size_t total_mem = max_old_gen_size + max_eden_size;
319 const double mem_free_limit = total_mem * (GCHeapFreeLimit/100.0);
320 const double mem_free_old_limit = max_old_gen_size * (GCHeapFreeLimit/100.0);
321 const double mem_free_eden_limit = max_eden_size * (GCHeapFreeLimit/100.0);
322 const double gc_cost_limit = GCTimeLimit/100.0;
323 size_t promo_limit = (size_t)(max_old_gen_size - avg_old_live()->average());
324 // But don't force a promo size below the current promo size. Otherwise,
325 // the promo size will shrink for no good reason.
326 promo_limit = MAX2(promo_limit, _promo_size);
327
328
329 log_trace(gc, ergo)(
330 "PSAdaptiveSizePolicy::check_gc_overhead_limit:"
331 " promo_limit: " SIZE_FORMAT
332 " max_eden_size: " SIZE_FORMAT
333 " total_free_limit: " SIZE_FORMAT
334 " max_old_gen_size: " SIZE_FORMAT
335 " max_eden_size: " SIZE_FORMAT
336 " mem_free_limit: " SIZE_FORMAT,
337 promo_limit, max_eden_size, total_free_limit,
338 max_old_gen_size, max_eden_size,
339 (size_t) mem_free_limit);
340
341 bool print_gc_overhead_limit_would_be_exceeded = false;
342 if (is_full_gc) {
343 if (gc_cost() > gc_cost_limit &&
344 free_in_old_gen < (size_t) mem_free_old_limit &&
345 free_in_eden < (size_t) mem_free_eden_limit) {
346 // Collections, on average, are taking too much time, and
347 // gc_cost() > gc_cost_limit
348 // we have too little space available after a full gc.
349 // total_free_limit < mem_free_limit
350 // where
351 // total_free_limit is the free space available in
352 // both generations
353 // total_mem is the total space available for allocation
354 // in both generations (survivor spaces are not included
355 // just as they are not included in eden_limit).
356 // mem_free_limit is a fraction of total_mem judged to be an
357 // acceptable amount that is still unused.
358 // The heap can ask for the value of this variable when deciding
359 // whether to thrown an OutOfMemory error.
360 // Note that the gc time limit test only works for the collections
361 // of the young gen + tenured gen and not for collections of the
362 // permanent gen. That is because the calculation of the space
363 // freed by the collection is the free space in the young gen +
364 // tenured gen.
365 // At this point the GC overhead limit is being exceeded.
366 inc_gc_overhead_limit_count();
367 if (UseGCOverheadLimit) {
368 if (gc_overhead_limit_count() >=
369 AdaptiveSizePolicyGCTimeLimitThreshold){
370 // All conditions have been met for throwing an out-of-memory
371 set_gc_overhead_limit_exceeded(true);
372 // Avoid consecutive OOM due to the gc time limit by resetting
373 // the counter.
374 reset_gc_overhead_limit_count();
375 } else {
376 // The required consecutive collections which exceed the
377 // GC time limit may or may not have been reached. We
378 // are approaching that condition and so as not to
379 // throw an out-of-memory before all SoftRef's have been
380 // cleared, set _should_clear_all_soft_refs in CollectorPolicy.
381 // The clearing will be done on the next GC.
382 bool near_limit = gc_overhead_limit_near();
383 if (near_limit) {
384 soft_ref_policy->set_should_clear_all_soft_refs(true);
385 log_trace(gc, ergo)("Nearing GC overhead limit, will be clearing all SoftReference");
386 }
387 }
388 }
389 // Set this even when the overhead limit will not
390 // cause an out-of-memory. Diagnostic message indicating
391 // that the overhead limit is being exceeded is sometimes
392 // printed.
393 print_gc_overhead_limit_would_be_exceeded = true;
394
395 } else {
396 // Did not exceed overhead limits
397 reset_gc_overhead_limit_count();
398 }
399 }
400
401 if (UseGCOverheadLimit) {
402 if (gc_overhead_limit_exceeded()) {
403 log_trace(gc, ergo)("GC is exceeding overhead limit of " UINTX_FORMAT "%%", GCTimeLimit);
404 reset_gc_overhead_limit_count();
405 } else if (print_gc_overhead_limit_would_be_exceeded) {
406 assert(gc_overhead_limit_count() > 0, "Should not be printing");
407 log_trace(gc, ergo)("GC would exceed overhead limit of " UINTX_FORMAT "%% %d consecutive time(s)",
408 GCTimeLimit, gc_overhead_limit_count());
409 }
410 }
411 }
412 // Printing
413
414 bool AdaptiveSizePolicy::print() const {
415 assert(UseAdaptiveSizePolicy, "UseAdaptiveSizePolicy need to be enabled.");
416
417 if (!log_is_enabled(Debug, gc, ergo)) {
418 return false;
419 }
420
421 // Print goal for which action is needed.
422 char* action = NULL;
423 bool change_for_pause = false;
424 if ((change_old_gen_for_maj_pauses() ==
425 decrease_old_gen_for_maj_pauses_true) ||
426 (change_young_gen_for_min_pauses() ==
427 decrease_young_gen_for_min_pauses_true)) {
428 action = (char*) " *** pause time goal ***";
429 change_for_pause = true;
430 } else if ((change_old_gen_for_throughput() ==
|
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/shared/adaptiveSizePolicy.hpp"
27 #include "gc/shared/gcCause.hpp"
28 #include "gc/shared/gcUtil.inline.hpp"
29 #include "logging/log.hpp"
30 #include "runtime/timer.hpp"
31
32 elapsedTimer AdaptiveSizePolicy::_minor_timer;
33 elapsedTimer AdaptiveSizePolicy::_major_timer;
34
35 // The throughput goal is implemented as
36 // _throughput_goal = 1 - ( 1 / (1 + gc_cost_ratio))
37 // gc_cost_ratio is the ratio
38 // application cost / gc cost
39 // For example a gc_cost_ratio of 4 translates into a
40 // throughput goal of .80
41
42 AdaptiveSizePolicy::AdaptiveSizePolicy(size_t init_eden_size,
43 size_t init_promo_size,
44 size_t init_survivor_size,
45 double gc_pause_goal_sec,
46 uint gc_cost_ratio) :
47 _throughput_goal(1.0 - double(1.0 / (1.0 + (double) gc_cost_ratio))),
48 _eden_size(init_eden_size),
49 _promo_size(init_promo_size),
50 _survivor_size(init_survivor_size),
51 _latest_minor_mutator_interval_seconds(0),
52 _threshold_tolerance_percent(1.0 + ThresholdTolerance/100.0),
53 _gc_pause_goal_sec(gc_pause_goal_sec),
54 _young_gen_change_for_minor_throughput(0),
55 _old_gen_change_for_major_throughput(0) {
56 _avg_minor_pause =
57 new AdaptivePaddedAverage(AdaptiveTimeWeight, PausePadding);
58 _avg_minor_interval = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
59 _avg_minor_gc_cost = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
60 _avg_major_gc_cost = new AdaptiveWeightedAverage(AdaptiveTimeWeight);
61
62 _avg_young_live = new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight);
63 _avg_old_live = new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight);
64 _avg_eden_live = new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight);
65
66 _avg_survived = new AdaptivePaddedAverage(AdaptiveSizePolicyWeight,
67 SurvivorPadding);
68 _avg_pretenured = new AdaptivePaddedNoZeroDevAverage(
69 AdaptiveSizePolicyWeight,
70 SurvivorPadding);
71
72 _minor_pause_old_estimator =
73 new LinearLeastSquareFit(AdaptiveSizePolicyWeight);
74 _minor_pause_young_estimator =
75 new LinearLeastSquareFit(AdaptiveSizePolicyWeight);
254 avg_major_interval, time_since_last_major_gc);
255 log_trace(gc, ergo)(" major gc cost: %f decayed major gc cost: %f",
256 major_gc_cost(), decayed_major_gc_cost);
257 }
258 }
259 double result = MIN2(1.0, decayed_major_gc_cost + minor_gc_cost());
260 return result;
261 }
262
263
264 void AdaptiveSizePolicy::clear_generation_free_space_flags() {
265 set_change_young_gen_for_min_pauses(0);
266 set_change_old_gen_for_maj_pauses(0);
267
268 set_change_old_gen_for_throughput(0);
269 set_change_young_gen_for_throughput(0);
270 set_decrease_for_footprint(0);
271 set_decide_at_full_gc(0);
272 }
273
274 class AdaptiveSizePolicyTimeOverheadTester: public GCOverheadTester {
275 double _gc_cost;
276
277 public:
278 AdaptiveSizePolicyTimeOverheadTester(double gc_cost) : _gc_cost(gc_cost) {}
279
280 bool is_exceeded() {
281 // Note that the gc time limit test only works for the collections
282 // of the young gen + tenured gen and not for collections of the
283 // permanent gen. That is because the calculation of the space
284 // freed by the collection is the free space in the young gen +
285 // tenured gen.
286 return _gc_cost > (GCTimeLimit / 100.0);
287 }
288 };
289
290 class AdaptiveSizePolicySpaceOverheadTester: public GCOverheadTester {
291 size_t _eden_live;
292 size_t _max_old_gen_size;
293 size_t _max_eden_size;
294 size_t _promo_size;
295 double _avg_eden_live;
296 double _avg_old_live;
297
298 public:
299 AdaptiveSizePolicySpaceOverheadTester(size_t eden_live,
300 size_t max_old_gen_size,
301 size_t max_eden_size,
302 size_t promo_size,
303 double avg_eden_live,
304 double avg_old_live) :
305 _eden_live(eden_live),
306 _max_old_gen_size(max_old_gen_size),
307 _max_eden_size(max_eden_size),
308 _promo_size(promo_size),
309 _avg_eden_live(avg_eden_live),
310 _avg_old_live(avg_old_live) {}
311
312 bool is_exceeded() {
313 // _max_eden_size is the upper limit on the size of eden based on
314 // the maximum size of the young generation and the sizes
315 // of the survivor space.
316 // The question being asked is whether the space being recovered by
317 // a collection is low.
318 // free_in_eden is the free space in eden after a collection and
319 // free_in_old_gen is the free space in the old generation after
320 // a collection.
321 //
322 // Use the minimum of the current value of the live in eden
323 // or the average of the live in eden.
324 // If the current value drops quickly, that should be taken
325 // into account (i.e., don't trigger if the amount of free
326 // space has suddenly jumped up). If the current is much
327 // higher than the average, use the average since it represents
328 // the longer term behavior.
329 const size_t live_in_eden =
330 MIN2(_eden_live, (size_t)_avg_eden_live);
331 const size_t free_in_eden = _max_eden_size > live_in_eden ?
332 _max_eden_size - live_in_eden : 0;
333 const size_t free_in_old_gen = (size_t)(_max_old_gen_size - _avg_old_live);
334 const size_t total_free_limit = free_in_old_gen + free_in_eden;
335 const size_t total_mem = _max_old_gen_size + _max_eden_size;
336 const double free_limit_ratio = GCHeapFreeLimit / 100.0;
337 const double mem_free_limit = total_mem * free_limit_ratio;
338 const double mem_free_old_limit = _max_old_gen_size * free_limit_ratio;
339 const double mem_free_eden_limit = _max_eden_size * free_limit_ratio;
340 size_t promo_limit = (size_t)(_max_old_gen_size - _avg_old_live);
341 // But don't force a promo size below the current promo size. Otherwise,
342 // the promo size will shrink for no good reason.
343 promo_limit = MAX2(promo_limit, _promo_size);
344
345 log_trace(gc, ergo)(
346 "AdaptiveSizePolicySpaceOverheadTester::is_exceeded:"
347 " promo_limit: " SIZE_FORMAT
348 " max_eden_size: " SIZE_FORMAT
349 " total_free_limit: " SIZE_FORMAT
350 " max_old_gen_size: " SIZE_FORMAT
351 " max_eden_size: " SIZE_FORMAT
352 " mem_free_limit: " SIZE_FORMAT,
353 promo_limit, _max_eden_size, total_free_limit,
354 _max_old_gen_size, _max_eden_size,
355 (size_t)mem_free_limit);
356
357 return free_in_old_gen < (size_t)mem_free_old_limit &&
358 free_in_eden < (size_t)mem_free_eden_limit;
359 }
360 };
361
362 void AdaptiveSizePolicy::check_gc_overhead_limit(
363 size_t eden_live,
364 size_t max_old_gen_size,
365 size_t max_eden_size,
366 bool is_full_gc,
367 GCCause::Cause gc_cause,
368 SoftRefPolicy* soft_ref_policy) {
369
370 AdaptiveSizePolicyTimeOverheadTester time_overhead(gc_cost());
371 AdaptiveSizePolicySpaceOverheadTester space_overhead(eden_live,
372 max_old_gen_size,
373 max_eden_size,
374 _promo_size,
375 avg_eden_live()->average(),
376 avg_old_live()->average());
377 _overhead_checker.check_gc_overhead_limit(&time_overhead,
378 &space_overhead,
379 is_full_gc,
380 gc_cause,
381 soft_ref_policy);
382 }
383 // Printing
384
385 bool AdaptiveSizePolicy::print() const {
386 assert(UseAdaptiveSizePolicy, "UseAdaptiveSizePolicy need to be enabled.");
387
388 if (!log_is_enabled(Debug, gc, ergo)) {
389 return false;
390 }
391
392 // Print goal for which action is needed.
393 char* action = NULL;
394 bool change_for_pause = false;
395 if ((change_old_gen_for_maj_pauses() ==
396 decrease_old_gen_for_maj_pauses_true) ||
397 (change_young_gen_for_min_pauses() ==
398 decrease_young_gen_for_min_pauses_true)) {
399 action = (char*) " *** pause time goal ***";
400 change_for_pause = true;
401 } else if ((change_old_gen_for_throughput() ==
|