| 1 | /* |
| 2 | * Copyright (c) 2004, 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/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 | _avg_minor_pause(new AdaptivePaddedAverage(AdaptiveTimeWeight, PausePadding)), |
| 52 | _avg_minor_interval(new AdaptiveWeightedAverage(AdaptiveTimeWeight)), |
| 53 | _avg_minor_gc_cost(new AdaptiveWeightedAverage(AdaptiveTimeWeight)), |
| 54 | _avg_major_interval(new AdaptiveWeightedAverage(AdaptiveTimeWeight)), |
| 55 | _avg_major_gc_cost(new AdaptiveWeightedAverage(AdaptiveTimeWeight)), |
| 56 | _avg_young_live(new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight)), |
| 57 | _avg_eden_live(new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight)), |
| 58 | _avg_old_live(new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight)), |
| 59 | _avg_survived(new AdaptivePaddedAverage(AdaptiveSizePolicyWeight, SurvivorPadding)), |
| 60 | _avg_pretenured(new AdaptivePaddedNoZeroDevAverage(AdaptiveSizePolicyWeight, SurvivorPadding)), |
| 61 | _minor_pause_old_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)), |
| 62 | _minor_pause_young_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)), |
| 63 | _minor_collection_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)), |
| 64 | _major_collection_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)), |
| 65 | _latest_minor_mutator_interval_seconds(0), |
| 66 | _threshold_tolerance_percent(1.0 + ThresholdTolerance/100.0), |
| 67 | _gc_pause_goal_sec(gc_pause_goal_sec), |
| 68 | _young_gen_policy_is_ready(false), |
| 69 | _change_young_gen_for_min_pauses(0), |
| 70 | _change_old_gen_for_maj_pauses(0), |
| 71 | _change_old_gen_for_throughput(0), |
| 72 | _change_young_gen_for_throughput(0), |
| 73 | _increment_tenuring_threshold_for_gc_cost(false), |
| 74 | _decrement_tenuring_threshold_for_gc_cost(false), |
| 75 | _decrement_tenuring_threshold_for_survivor_limit(false), |
| 76 | _decrease_for_footprint(0), |
| 77 | _decide_at_full_gc(0), |
| 78 | _young_gen_change_for_minor_throughput(0), |
| 79 | _old_gen_change_for_major_throughput(0) { |
| 80 | |
| 81 | // Start the timers |
| 82 | _minor_timer.start(); |
| 83 | } |
| 84 | |
| 85 | bool AdaptiveSizePolicy::tenuring_threshold_change() const { |
| 86 | return decrement_tenuring_threshold_for_gc_cost() || |
| 87 | increment_tenuring_threshold_for_gc_cost() || |
| 88 | decrement_tenuring_threshold_for_survivor_limit(); |
| 89 | } |
| 90 | |
| 91 | void AdaptiveSizePolicy::minor_collection_begin() { |
| 92 | // Update the interval time |
| 93 | _minor_timer.stop(); |
| 94 | // Save most recent collection time |
| 95 | _latest_minor_mutator_interval_seconds = _minor_timer.seconds(); |
| 96 | _minor_timer.reset(); |
| 97 | _minor_timer.start(); |
| 98 | } |
| 99 | |
| 100 | void AdaptiveSizePolicy::update_minor_pause_young_estimator( |
| 101 | double minor_pause_in_ms) { |
| 102 | double eden_size_in_mbytes = ((double)_eden_size)/((double)M); |
| 103 | _minor_pause_young_estimator->update(eden_size_in_mbytes, |
| 104 | minor_pause_in_ms); |
| 105 | } |
| 106 | |
| 107 | void AdaptiveSizePolicy::minor_collection_end(GCCause::Cause gc_cause) { |
| 108 | // Update the pause time. |
| 109 | _minor_timer.stop(); |
| 110 | |
| 111 | if (!GCCause::is_user_requested_gc(gc_cause) || |
| 112 | UseAdaptiveSizePolicyWithSystemGC) { |
| 113 | double minor_pause_in_seconds = _minor_timer.seconds(); |
| 114 | double minor_pause_in_ms = minor_pause_in_seconds * MILLIUNITS; |
| 115 | |
| 116 | // Sample for performance counter |
| 117 | _avg_minor_pause->sample(minor_pause_in_seconds); |
| 118 | |
| 119 | // Cost of collection (unit-less) |
| 120 | double collection_cost = 0.0; |
| 121 | if ((_latest_minor_mutator_interval_seconds > 0.0) && |
| 122 | (minor_pause_in_seconds > 0.0)) { |
| 123 | double interval_in_seconds = |
| 124 | _latest_minor_mutator_interval_seconds + minor_pause_in_seconds; |
| 125 | collection_cost = |
| 126 | minor_pause_in_seconds / interval_in_seconds; |
| 127 | _avg_minor_gc_cost->sample(collection_cost); |
| 128 | // Sample for performance counter |
| 129 | _avg_minor_interval->sample(interval_in_seconds); |
| 130 | } |
| 131 | |
| 132 | // The policy does not have enough data until at least some |
| 133 | // young collections have been done. |
| 134 | _young_gen_policy_is_ready = |
| 135 | (_avg_minor_gc_cost->count() >= AdaptiveSizePolicyReadyThreshold); |
| 136 | |
| 137 | // Calculate variables used to estimate pause time vs. gen sizes |
| 138 | double eden_size_in_mbytes = ((double)_eden_size) / ((double)M); |
| 139 | update_minor_pause_young_estimator(minor_pause_in_ms); |
| 140 | update_minor_pause_old_estimator(minor_pause_in_ms); |
| 141 | |
| 142 | log_trace(gc, ergo)("AdaptiveSizePolicy::minor_collection_end: minor gc cost: %f average: %f" , |
| 143 | collection_cost, _avg_minor_gc_cost->average()); |
| 144 | log_trace(gc, ergo)(" minor pause: %f minor period %f" , |
| 145 | minor_pause_in_ms, _latest_minor_mutator_interval_seconds * MILLIUNITS); |
| 146 | |
| 147 | // Calculate variable used to estimate collection cost vs. gen sizes |
| 148 | assert(collection_cost >= 0.0, "Expected to be non-negative" ); |
| 149 | _minor_collection_estimator->update(eden_size_in_mbytes, collection_cost); |
| 150 | } |
| 151 | |
| 152 | // Interval times use this timer to measure the mutator time. |
| 153 | // Reset the timer after the GC pause. |
| 154 | _minor_timer.reset(); |
| 155 | _minor_timer.start(); |
| 156 | } |
| 157 | |
| 158 | size_t AdaptiveSizePolicy::eden_increment(size_t cur_eden, uint percent_change) { |
| 159 | size_t eden_heap_delta; |
| 160 | eden_heap_delta = cur_eden / 100 * percent_change; |
| 161 | return eden_heap_delta; |
| 162 | } |
| 163 | |
| 164 | size_t AdaptiveSizePolicy::eden_increment(size_t cur_eden) { |
| 165 | return eden_increment(cur_eden, YoungGenerationSizeIncrement); |
| 166 | } |
| 167 | |
| 168 | size_t AdaptiveSizePolicy::eden_decrement(size_t cur_eden) { |
| 169 | size_t eden_heap_delta = eden_increment(cur_eden) / |
| 170 | AdaptiveSizeDecrementScaleFactor; |
| 171 | return eden_heap_delta; |
| 172 | } |
| 173 | |
| 174 | size_t AdaptiveSizePolicy::promo_increment(size_t cur_promo, uint percent_change) { |
| 175 | size_t promo_heap_delta; |
| 176 | promo_heap_delta = cur_promo / 100 * percent_change; |
| 177 | return promo_heap_delta; |
| 178 | } |
| 179 | |
| 180 | size_t AdaptiveSizePolicy::promo_increment(size_t cur_promo) { |
| 181 | return promo_increment(cur_promo, TenuredGenerationSizeIncrement); |
| 182 | } |
| 183 | |
| 184 | size_t AdaptiveSizePolicy::promo_decrement(size_t cur_promo) { |
| 185 | size_t promo_heap_delta = promo_increment(cur_promo); |
| 186 | promo_heap_delta = promo_heap_delta / AdaptiveSizeDecrementScaleFactor; |
| 187 | return promo_heap_delta; |
| 188 | } |
| 189 | |
| 190 | double AdaptiveSizePolicy::time_since_major_gc() const { |
| 191 | _major_timer.stop(); |
| 192 | double result = _major_timer.seconds(); |
| 193 | _major_timer.start(); |
| 194 | return result; |
| 195 | } |
| 196 | |
| 197 | // Linear decay of major gc cost |
| 198 | double AdaptiveSizePolicy::decaying_major_gc_cost() const { |
| 199 | double major_interval = major_gc_interval_average_for_decay(); |
| 200 | double major_gc_cost_average = major_gc_cost(); |
| 201 | double decayed_major_gc_cost = major_gc_cost_average; |
| 202 | if(time_since_major_gc() > 0.0) { |
| 203 | decayed_major_gc_cost = major_gc_cost() * |
| 204 | (((double) AdaptiveSizeMajorGCDecayTimeScale) * major_interval) |
| 205 | / time_since_major_gc(); |
| 206 | } |
| 207 | |
| 208 | // The decayed cost should always be smaller than the |
| 209 | // average cost but the vagaries of finite arithmetic could |
| 210 | // produce a larger value in decayed_major_gc_cost so protect |
| 211 | // against that. |
| 212 | return MIN2(major_gc_cost_average, decayed_major_gc_cost); |
| 213 | } |
| 214 | |
| 215 | // Use a value of the major gc cost that has been decayed |
| 216 | // by the factor |
| 217 | // |
| 218 | // average-interval-between-major-gc * AdaptiveSizeMajorGCDecayTimeScale / |
| 219 | // time-since-last-major-gc |
| 220 | // |
| 221 | // if the average-interval-between-major-gc * AdaptiveSizeMajorGCDecayTimeScale |
| 222 | // is less than time-since-last-major-gc. |
| 223 | // |
| 224 | // In cases where there are initial major gc's that |
| 225 | // are of a relatively high cost but no later major |
| 226 | // gc's, the total gc cost can remain high because |
| 227 | // the major gc cost remains unchanged (since there are no major |
| 228 | // gc's). In such a situation the value of the unchanging |
| 229 | // major gc cost can keep the mutator throughput below |
| 230 | // the goal when in fact the major gc cost is becoming diminishingly |
| 231 | // small. Use the decaying gc cost only to decide whether to |
| 232 | // adjust for throughput. Using it also to determine the adjustment |
| 233 | // to be made for throughput also seems reasonable but there is |
| 234 | // no test case to use to decide if it is the right thing to do |
| 235 | // don't do it yet. |
| 236 | |
| 237 | double AdaptiveSizePolicy::decaying_gc_cost() const { |
| 238 | double decayed_major_gc_cost = major_gc_cost(); |
| 239 | double avg_major_interval = major_gc_interval_average_for_decay(); |
| 240 | if (UseAdaptiveSizeDecayMajorGCCost && |
| 241 | (AdaptiveSizeMajorGCDecayTimeScale > 0) && |
| 242 | (avg_major_interval > 0.00)) { |
| 243 | double time_since_last_major_gc = time_since_major_gc(); |
| 244 | |
| 245 | // Decay the major gc cost? |
| 246 | if (time_since_last_major_gc > |
| 247 | ((double) AdaptiveSizeMajorGCDecayTimeScale) * avg_major_interval) { |
| 248 | |
| 249 | // Decay using the time-since-last-major-gc |
| 250 | decayed_major_gc_cost = decaying_major_gc_cost(); |
| 251 | log_trace(gc, ergo)("decaying_gc_cost: major interval average: %f time since last major gc: %f" , |
| 252 | avg_major_interval, time_since_last_major_gc); |
| 253 | log_trace(gc, ergo)(" major gc cost: %f decayed major gc cost: %f" , |
| 254 | major_gc_cost(), decayed_major_gc_cost); |
| 255 | } |
| 256 | } |
| 257 | double result = MIN2(1.0, decayed_major_gc_cost + minor_gc_cost()); |
| 258 | return result; |
| 259 | } |
| 260 | |
| 261 | |
| 262 | void AdaptiveSizePolicy::clear_generation_free_space_flags() { |
| 263 | set_change_young_gen_for_min_pauses(0); |
| 264 | set_change_old_gen_for_maj_pauses(0); |
| 265 | |
| 266 | set_change_old_gen_for_throughput(0); |
| 267 | set_change_young_gen_for_throughput(0); |
| 268 | set_decrease_for_footprint(0); |
| 269 | set_decide_at_full_gc(0); |
| 270 | } |
| 271 | |
| 272 | class AdaptiveSizePolicyTimeOverheadTester: public GCOverheadTester { |
| 273 | double _gc_cost; |
| 274 | |
| 275 | public: |
| 276 | AdaptiveSizePolicyTimeOverheadTester(double gc_cost) : _gc_cost(gc_cost) {} |
| 277 | |
| 278 | bool is_exceeded() { |
| 279 | return _gc_cost > (GCTimeLimit / 100.0); |
| 280 | } |
| 281 | }; |
| 282 | |
| 283 | class AdaptiveSizePolicySpaceOverheadTester: public GCOverheadTester { |
| 284 | size_t _eden_live; |
| 285 | size_t _max_old_gen_size; |
| 286 | size_t _max_eden_size; |
| 287 | size_t _promo_size; |
| 288 | double _avg_eden_live; |
| 289 | double _avg_old_live; |
| 290 | |
| 291 | public: |
| 292 | AdaptiveSizePolicySpaceOverheadTester(size_t eden_live, |
| 293 | size_t max_old_gen_size, |
| 294 | size_t max_eden_size, |
| 295 | size_t promo_size, |
| 296 | double avg_eden_live, |
| 297 | double avg_old_live) : |
| 298 | _eden_live(eden_live), |
| 299 | _max_old_gen_size(max_old_gen_size), |
| 300 | _max_eden_size(max_eden_size), |
| 301 | _promo_size(promo_size), |
| 302 | _avg_eden_live(avg_eden_live), |
| 303 | _avg_old_live(avg_old_live) {} |
| 304 | |
| 305 | bool is_exceeded() { |
| 306 | // _max_eden_size is the upper limit on the size of eden based on |
| 307 | // the maximum size of the young generation and the sizes |
| 308 | // of the survivor space. |
| 309 | // The question being asked is whether the space being recovered by |
| 310 | // a collection is low. |
| 311 | // free_in_eden is the free space in eden after a collection and |
| 312 | // free_in_old_gen is the free space in the old generation after |
| 313 | // a collection. |
| 314 | // |
| 315 | // Use the minimum of the current value of the live in eden |
| 316 | // or the average of the live in eden. |
| 317 | // If the current value drops quickly, that should be taken |
| 318 | // into account (i.e., don't trigger if the amount of free |
| 319 | // space has suddenly jumped up). If the current is much |
| 320 | // higher than the average, use the average since it represents |
| 321 | // the longer term behavior. |
| 322 | const size_t live_in_eden = |
| 323 | MIN2(_eden_live, (size_t)_avg_eden_live); |
| 324 | const size_t free_in_eden = _max_eden_size > live_in_eden ? |
| 325 | _max_eden_size - live_in_eden : 0; |
| 326 | const size_t free_in_old_gen = (size_t)(_max_old_gen_size - _avg_old_live); |
| 327 | const size_t total_free_limit = free_in_old_gen + free_in_eden; |
| 328 | const size_t total_mem = _max_old_gen_size + _max_eden_size; |
| 329 | const double free_limit_ratio = GCHeapFreeLimit / 100.0; |
| 330 | const double mem_free_limit = total_mem * free_limit_ratio; |
| 331 | const double mem_free_old_limit = _max_old_gen_size * free_limit_ratio; |
| 332 | const double mem_free_eden_limit = _max_eden_size * free_limit_ratio; |
| 333 | size_t promo_limit = (size_t)(_max_old_gen_size - _avg_old_live); |
| 334 | // But don't force a promo size below the current promo size. Otherwise, |
| 335 | // the promo size will shrink for no good reason. |
| 336 | promo_limit = MAX2(promo_limit, _promo_size); |
| 337 | |
| 338 | log_trace(gc, ergo)( |
| 339 | "AdaptiveSizePolicySpaceOverheadTester::is_exceeded:" |
| 340 | " promo_limit: " SIZE_FORMAT |
| 341 | " max_eden_size: " SIZE_FORMAT |
| 342 | " total_free_limit: " SIZE_FORMAT |
| 343 | " max_old_gen_size: " SIZE_FORMAT |
| 344 | " max_eden_size: " SIZE_FORMAT |
| 345 | " mem_free_limit: " SIZE_FORMAT, |
| 346 | promo_limit, _max_eden_size, total_free_limit, |
| 347 | _max_old_gen_size, _max_eden_size, |
| 348 | (size_t)mem_free_limit); |
| 349 | |
| 350 | return free_in_old_gen < (size_t)mem_free_old_limit && |
| 351 | free_in_eden < (size_t)mem_free_eden_limit; |
| 352 | } |
| 353 | }; |
| 354 | |
| 355 | void AdaptiveSizePolicy::check_gc_overhead_limit( |
| 356 | size_t eden_live, |
| 357 | size_t max_old_gen_size, |
| 358 | size_t max_eden_size, |
| 359 | bool is_full_gc, |
| 360 | GCCause::Cause gc_cause, |
| 361 | SoftRefPolicy* soft_ref_policy) { |
| 362 | |
| 363 | AdaptiveSizePolicyTimeOverheadTester time_overhead(gc_cost()); |
| 364 | AdaptiveSizePolicySpaceOverheadTester space_overhead(eden_live, |
| 365 | max_old_gen_size, |
| 366 | max_eden_size, |
| 367 | _promo_size, |
| 368 | avg_eden_live()->average(), |
| 369 | avg_old_live()->average()); |
| 370 | _overhead_checker.check_gc_overhead_limit(&time_overhead, |
| 371 | &space_overhead, |
| 372 | is_full_gc, |
| 373 | gc_cause, |
| 374 | soft_ref_policy); |
| 375 | } |
| 376 | // Printing |
| 377 | |
| 378 | bool AdaptiveSizePolicy::print() const { |
| 379 | assert(UseAdaptiveSizePolicy, "UseAdaptiveSizePolicy need to be enabled." ); |
| 380 | |
| 381 | if (!log_is_enabled(Debug, gc, ergo)) { |
| 382 | return false; |
| 383 | } |
| 384 | |
| 385 | // Print goal for which action is needed. |
| 386 | char* action = NULL; |
| 387 | bool change_for_pause = false; |
| 388 | if ((change_old_gen_for_maj_pauses() == |
| 389 | decrease_old_gen_for_maj_pauses_true) || |
| 390 | (change_young_gen_for_min_pauses() == |
| 391 | decrease_young_gen_for_min_pauses_true)) { |
| 392 | action = (char*) " *** pause time goal ***" ; |
| 393 | change_for_pause = true; |
| 394 | } else if ((change_old_gen_for_throughput() == |
| 395 | increase_old_gen_for_throughput_true) || |
| 396 | (change_young_gen_for_throughput() == |
| 397 | increase_young_gen_for_througput_true)) { |
| 398 | action = (char*) " *** throughput goal ***" ; |
| 399 | } else if (decrease_for_footprint()) { |
| 400 | action = (char*) " *** reduced footprint ***" ; |
| 401 | } else { |
| 402 | // No actions were taken. This can legitimately be the |
| 403 | // situation if not enough data has been gathered to make |
| 404 | // decisions. |
| 405 | return false; |
| 406 | } |
| 407 | |
| 408 | // Pauses |
| 409 | // Currently the size of the old gen is only adjusted to |
| 410 | // change the major pause times. |
| 411 | char* young_gen_action = NULL; |
| 412 | char* tenured_gen_action = NULL; |
| 413 | |
| 414 | char* shrink_msg = (char*) "(attempted to shrink)" ; |
| 415 | char* grow_msg = (char*) "(attempted to grow)" ; |
| 416 | char* no_change_msg = (char*) "(no change)" ; |
| 417 | if (change_young_gen_for_min_pauses() == |
| 418 | decrease_young_gen_for_min_pauses_true) { |
| 419 | young_gen_action = shrink_msg; |
| 420 | } else if (change_for_pause) { |
| 421 | young_gen_action = no_change_msg; |
| 422 | } |
| 423 | |
| 424 | if (change_old_gen_for_maj_pauses() == decrease_old_gen_for_maj_pauses_true) { |
| 425 | tenured_gen_action = shrink_msg; |
| 426 | } else if (change_for_pause) { |
| 427 | tenured_gen_action = no_change_msg; |
| 428 | } |
| 429 | |
| 430 | // Throughput |
| 431 | if (change_old_gen_for_throughput() == increase_old_gen_for_throughput_true) { |
| 432 | assert(change_young_gen_for_throughput() == |
| 433 | increase_young_gen_for_througput_true, |
| 434 | "Both generations should be growing" ); |
| 435 | young_gen_action = grow_msg; |
| 436 | tenured_gen_action = grow_msg; |
| 437 | } else if (change_young_gen_for_throughput() == |
| 438 | increase_young_gen_for_througput_true) { |
| 439 | // Only the young generation may grow at start up (before |
| 440 | // enough full collections have been done to grow the old generation). |
| 441 | young_gen_action = grow_msg; |
| 442 | tenured_gen_action = no_change_msg; |
| 443 | } |
| 444 | |
| 445 | // Minimum footprint |
| 446 | if (decrease_for_footprint() != 0) { |
| 447 | young_gen_action = shrink_msg; |
| 448 | tenured_gen_action = shrink_msg; |
| 449 | } |
| 450 | |
| 451 | log_debug(gc, ergo)("UseAdaptiveSizePolicy actions to meet %s" , action); |
| 452 | log_debug(gc, ergo)(" GC overhead (%%)" ); |
| 453 | log_debug(gc, ergo)(" Young generation: %7.2f\t %s" , |
| 454 | 100.0 * avg_minor_gc_cost()->average(), young_gen_action); |
| 455 | log_debug(gc, ergo)(" Tenured generation: %7.2f\t %s" , |
| 456 | 100.0 * avg_major_gc_cost()->average(), tenured_gen_action); |
| 457 | return true; |
| 458 | } |
| 459 | |
| 460 | void AdaptiveSizePolicy::print_tenuring_threshold( uint new_tenuring_threshold_arg) const { |
| 461 | // Tenuring threshold |
| 462 | if (decrement_tenuring_threshold_for_survivor_limit()) { |
| 463 | log_debug(gc, ergo)("Tenuring threshold: (attempted to decrease to avoid survivor space overflow) = %u" , new_tenuring_threshold_arg); |
| 464 | } else if (decrement_tenuring_threshold_for_gc_cost()) { |
| 465 | log_debug(gc, ergo)("Tenuring threshold: (attempted to decrease to balance GC costs) = %u" , new_tenuring_threshold_arg); |
| 466 | } else if (increment_tenuring_threshold_for_gc_cost()) { |
| 467 | log_debug(gc, ergo)("Tenuring threshold: (attempted to increase to balance GC costs) = %u" , new_tenuring_threshold_arg); |
| 468 | } else { |
| 469 | assert(!tenuring_threshold_change(), "(no change was attempted)" ); |
| 470 | } |
| 471 | } |
| 472 | |