Tue, 23 Nov 2010 13:22:55 -0800
6989984: Use standard include model for Hospot
Summary: Replaced MakeDeps and the includeDB files with more standardized solutions.
Reviewed-by: coleenp, kvn, kamg
duke@435 | 1 | /* |
trims@1907 | 2 | * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. |
duke@435 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@435 | 4 | * |
duke@435 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@435 | 6 | * under the terms of the GNU General Public License version 2 only, as |
duke@435 | 7 | * published by the Free Software Foundation. |
duke@435 | 8 | * |
duke@435 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@435 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@435 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@435 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@435 | 13 | * accompanied this code). |
duke@435 | 14 | * |
duke@435 | 15 | * You should have received a copy of the GNU General Public License version |
duke@435 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@435 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@435 | 18 | * |
trims@1907 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
trims@1907 | 20 | * or visit www.oracle.com if you need additional information or have any |
trims@1907 | 21 | * questions. |
duke@435 | 22 | * |
duke@435 | 23 | */ |
duke@435 | 24 | |
stefank@2314 | 25 | #include "precompiled.hpp" |
stefank@2314 | 26 | #include "gc_implementation/shared/adaptiveSizePolicy.hpp" |
stefank@2314 | 27 | #include "gc_interface/gcCause.hpp" |
stefank@2314 | 28 | #include "memory/collectorPolicy.hpp" |
stefank@2314 | 29 | #include "runtime/timer.hpp" |
stefank@2314 | 30 | #include "utilities/ostream.hpp" |
duke@435 | 31 | elapsedTimer AdaptiveSizePolicy::_minor_timer; |
duke@435 | 32 | elapsedTimer AdaptiveSizePolicy::_major_timer; |
duke@435 | 33 | |
duke@435 | 34 | // The throughput goal is implemented as |
duke@435 | 35 | // _throughput_goal = 1 - ( 1 / (1 + gc_cost_ratio)) |
duke@435 | 36 | // gc_cost_ratio is the ratio |
duke@435 | 37 | // application cost / gc cost |
duke@435 | 38 | // For example a gc_cost_ratio of 4 translates into a |
duke@435 | 39 | // throughput goal of .80 |
duke@435 | 40 | |
duke@435 | 41 | AdaptiveSizePolicy::AdaptiveSizePolicy(size_t init_eden_size, |
duke@435 | 42 | size_t init_promo_size, |
duke@435 | 43 | size_t init_survivor_size, |
duke@435 | 44 | double gc_pause_goal_sec, |
duke@435 | 45 | uint gc_cost_ratio) : |
duke@435 | 46 | _eden_size(init_eden_size), |
duke@435 | 47 | _promo_size(init_promo_size), |
duke@435 | 48 | _survivor_size(init_survivor_size), |
duke@435 | 49 | _gc_pause_goal_sec(gc_pause_goal_sec), |
duke@435 | 50 | _throughput_goal(1.0 - double(1.0 / (1.0 + (double) gc_cost_ratio))), |
jmasa@1822 | 51 | _gc_overhead_limit_exceeded(false), |
jmasa@1822 | 52 | _print_gc_overhead_limit_would_be_exceeded(false), |
jmasa@1822 | 53 | _gc_overhead_limit_count(0), |
duke@435 | 54 | _latest_minor_mutator_interval_seconds(0), |
duke@435 | 55 | _threshold_tolerance_percent(1.0 + ThresholdTolerance/100.0), |
duke@435 | 56 | _young_gen_change_for_minor_throughput(0), |
duke@435 | 57 | _old_gen_change_for_major_throughput(0) { |
jmasa@1822 | 58 | assert(AdaptiveSizePolicyGCTimeLimitThreshold > 0, |
jmasa@1822 | 59 | "No opportunity to clear SoftReferences before GC overhead limit"); |
duke@435 | 60 | _avg_minor_pause = |
duke@435 | 61 | new AdaptivePaddedAverage(AdaptiveTimeWeight, PausePadding); |
duke@435 | 62 | _avg_minor_interval = new AdaptiveWeightedAverage(AdaptiveTimeWeight); |
duke@435 | 63 | _avg_minor_gc_cost = new AdaptiveWeightedAverage(AdaptiveTimeWeight); |
duke@435 | 64 | _avg_major_gc_cost = new AdaptiveWeightedAverage(AdaptiveTimeWeight); |
duke@435 | 65 | |
duke@435 | 66 | _avg_young_live = new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight); |
duke@435 | 67 | _avg_old_live = new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight); |
duke@435 | 68 | _avg_eden_live = new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight); |
duke@435 | 69 | |
duke@435 | 70 | _avg_survived = new AdaptivePaddedAverage(AdaptiveSizePolicyWeight, |
duke@435 | 71 | SurvivorPadding); |
duke@435 | 72 | _avg_pretenured = new AdaptivePaddedNoZeroDevAverage( |
duke@435 | 73 | AdaptiveSizePolicyWeight, |
duke@435 | 74 | SurvivorPadding); |
duke@435 | 75 | |
duke@435 | 76 | _minor_pause_old_estimator = |
duke@435 | 77 | new LinearLeastSquareFit(AdaptiveSizePolicyWeight); |
duke@435 | 78 | _minor_pause_young_estimator = |
duke@435 | 79 | new LinearLeastSquareFit(AdaptiveSizePolicyWeight); |
duke@435 | 80 | _minor_collection_estimator = |
duke@435 | 81 | new LinearLeastSquareFit(AdaptiveSizePolicyWeight); |
duke@435 | 82 | _major_collection_estimator = |
duke@435 | 83 | new LinearLeastSquareFit(AdaptiveSizePolicyWeight); |
duke@435 | 84 | |
duke@435 | 85 | // Start the timers |
duke@435 | 86 | _minor_timer.start(); |
duke@435 | 87 | |
duke@435 | 88 | _young_gen_policy_is_ready = false; |
duke@435 | 89 | } |
duke@435 | 90 | |
duke@435 | 91 | bool AdaptiveSizePolicy::tenuring_threshold_change() const { |
duke@435 | 92 | return decrement_tenuring_threshold_for_gc_cost() || |
duke@435 | 93 | increment_tenuring_threshold_for_gc_cost() || |
duke@435 | 94 | decrement_tenuring_threshold_for_survivor_limit(); |
duke@435 | 95 | } |
duke@435 | 96 | |
duke@435 | 97 | void AdaptiveSizePolicy::minor_collection_begin() { |
duke@435 | 98 | // Update the interval time |
duke@435 | 99 | _minor_timer.stop(); |
duke@435 | 100 | // Save most recent collection time |
duke@435 | 101 | _latest_minor_mutator_interval_seconds = _minor_timer.seconds(); |
duke@435 | 102 | _minor_timer.reset(); |
duke@435 | 103 | _minor_timer.start(); |
duke@435 | 104 | } |
duke@435 | 105 | |
duke@435 | 106 | void AdaptiveSizePolicy::update_minor_pause_young_estimator( |
duke@435 | 107 | double minor_pause_in_ms) { |
duke@435 | 108 | double eden_size_in_mbytes = ((double)_eden_size)/((double)M); |
duke@435 | 109 | _minor_pause_young_estimator->update(eden_size_in_mbytes, |
duke@435 | 110 | minor_pause_in_ms); |
duke@435 | 111 | } |
duke@435 | 112 | |
duke@435 | 113 | void AdaptiveSizePolicy::minor_collection_end(GCCause::Cause gc_cause) { |
duke@435 | 114 | // Update the pause time. |
duke@435 | 115 | _minor_timer.stop(); |
duke@435 | 116 | |
duke@435 | 117 | if (gc_cause != GCCause::_java_lang_system_gc || |
duke@435 | 118 | UseAdaptiveSizePolicyWithSystemGC) { |
duke@435 | 119 | double minor_pause_in_seconds = _minor_timer.seconds(); |
duke@435 | 120 | double minor_pause_in_ms = minor_pause_in_seconds * MILLIUNITS; |
duke@435 | 121 | |
duke@435 | 122 | // Sample for performance counter |
duke@435 | 123 | _avg_minor_pause->sample(minor_pause_in_seconds); |
duke@435 | 124 | |
duke@435 | 125 | // Cost of collection (unit-less) |
duke@435 | 126 | double collection_cost = 0.0; |
duke@435 | 127 | if ((_latest_minor_mutator_interval_seconds > 0.0) && |
duke@435 | 128 | (minor_pause_in_seconds > 0.0)) { |
duke@435 | 129 | double interval_in_seconds = |
duke@435 | 130 | _latest_minor_mutator_interval_seconds + minor_pause_in_seconds; |
duke@435 | 131 | collection_cost = |
duke@435 | 132 | minor_pause_in_seconds / interval_in_seconds; |
duke@435 | 133 | _avg_minor_gc_cost->sample(collection_cost); |
duke@435 | 134 | // Sample for performance counter |
duke@435 | 135 | _avg_minor_interval->sample(interval_in_seconds); |
duke@435 | 136 | } |
duke@435 | 137 | |
duke@435 | 138 | // The policy does not have enough data until at least some |
duke@435 | 139 | // minor collections have been done. |
duke@435 | 140 | _young_gen_policy_is_ready = |
duke@435 | 141 | (_avg_minor_gc_cost->count() >= AdaptiveSizePolicyReadyThreshold); |
duke@435 | 142 | |
duke@435 | 143 | // Calculate variables used to estimate pause time vs. gen sizes |
duke@435 | 144 | double eden_size_in_mbytes = ((double)_eden_size)/((double)M); |
duke@435 | 145 | update_minor_pause_young_estimator(minor_pause_in_ms); |
duke@435 | 146 | update_minor_pause_old_estimator(minor_pause_in_ms); |
duke@435 | 147 | |
duke@435 | 148 | if (PrintAdaptiveSizePolicy && Verbose) { |
duke@435 | 149 | gclog_or_tty->print("AdaptiveSizePolicy::minor_collection_end: " |
duke@435 | 150 | "minor gc cost: %f average: %f", collection_cost, |
duke@435 | 151 | _avg_minor_gc_cost->average()); |
duke@435 | 152 | gclog_or_tty->print_cr(" minor pause: %f minor period %f", |
duke@435 | 153 | minor_pause_in_ms, |
duke@435 | 154 | _latest_minor_mutator_interval_seconds * MILLIUNITS); |
duke@435 | 155 | } |
duke@435 | 156 | |
duke@435 | 157 | // Calculate variable used to estimate collection cost vs. gen sizes |
duke@435 | 158 | assert(collection_cost >= 0.0, "Expected to be non-negative"); |
duke@435 | 159 | _minor_collection_estimator->update(eden_size_in_mbytes, collection_cost); |
duke@435 | 160 | } |
duke@435 | 161 | |
duke@435 | 162 | // Interval times use this timer to measure the mutator time. |
duke@435 | 163 | // Reset the timer after the GC pause. |
duke@435 | 164 | _minor_timer.reset(); |
duke@435 | 165 | _minor_timer.start(); |
duke@435 | 166 | } |
duke@435 | 167 | |
duke@435 | 168 | size_t AdaptiveSizePolicy::eden_increment(size_t cur_eden, |
duke@435 | 169 | uint percent_change) { |
duke@435 | 170 | size_t eden_heap_delta; |
duke@435 | 171 | eden_heap_delta = cur_eden / 100 * percent_change; |
duke@435 | 172 | return eden_heap_delta; |
duke@435 | 173 | } |
duke@435 | 174 | |
duke@435 | 175 | size_t AdaptiveSizePolicy::eden_increment(size_t cur_eden) { |
duke@435 | 176 | return eden_increment(cur_eden, YoungGenerationSizeIncrement); |
duke@435 | 177 | } |
duke@435 | 178 | |
duke@435 | 179 | size_t AdaptiveSizePolicy::eden_decrement(size_t cur_eden) { |
duke@435 | 180 | size_t eden_heap_delta = eden_increment(cur_eden) / |
duke@435 | 181 | AdaptiveSizeDecrementScaleFactor; |
duke@435 | 182 | return eden_heap_delta; |
duke@435 | 183 | } |
duke@435 | 184 | |
duke@435 | 185 | size_t AdaptiveSizePolicy::promo_increment(size_t cur_promo, |
duke@435 | 186 | uint percent_change) { |
duke@435 | 187 | size_t promo_heap_delta; |
duke@435 | 188 | promo_heap_delta = cur_promo / 100 * percent_change; |
duke@435 | 189 | return promo_heap_delta; |
duke@435 | 190 | } |
duke@435 | 191 | |
duke@435 | 192 | size_t AdaptiveSizePolicy::promo_increment(size_t cur_promo) { |
duke@435 | 193 | return promo_increment(cur_promo, TenuredGenerationSizeIncrement); |
duke@435 | 194 | } |
duke@435 | 195 | |
duke@435 | 196 | size_t AdaptiveSizePolicy::promo_decrement(size_t cur_promo) { |
duke@435 | 197 | size_t promo_heap_delta = promo_increment(cur_promo); |
duke@435 | 198 | promo_heap_delta = promo_heap_delta / AdaptiveSizeDecrementScaleFactor; |
duke@435 | 199 | return promo_heap_delta; |
duke@435 | 200 | } |
duke@435 | 201 | |
duke@435 | 202 | double AdaptiveSizePolicy::time_since_major_gc() const { |
duke@435 | 203 | _major_timer.stop(); |
duke@435 | 204 | double result = _major_timer.seconds(); |
duke@435 | 205 | _major_timer.start(); |
duke@435 | 206 | return result; |
duke@435 | 207 | } |
duke@435 | 208 | |
duke@435 | 209 | // Linear decay of major gc cost |
duke@435 | 210 | double AdaptiveSizePolicy::decaying_major_gc_cost() const { |
duke@435 | 211 | double major_interval = major_gc_interval_average_for_decay(); |
duke@435 | 212 | double major_gc_cost_average = major_gc_cost(); |
duke@435 | 213 | double decayed_major_gc_cost = major_gc_cost_average; |
duke@435 | 214 | if(time_since_major_gc() > 0.0) { |
duke@435 | 215 | decayed_major_gc_cost = major_gc_cost() * |
duke@435 | 216 | (((double) AdaptiveSizeMajorGCDecayTimeScale) * major_interval) |
duke@435 | 217 | / time_since_major_gc(); |
duke@435 | 218 | } |
duke@435 | 219 | |
duke@435 | 220 | // The decayed cost should always be smaller than the |
duke@435 | 221 | // average cost but the vagaries of finite arithmetic could |
duke@435 | 222 | // produce a larger value in decayed_major_gc_cost so protect |
duke@435 | 223 | // against that. |
duke@435 | 224 | return MIN2(major_gc_cost_average, decayed_major_gc_cost); |
duke@435 | 225 | } |
duke@435 | 226 | |
duke@435 | 227 | // Use a value of the major gc cost that has been decayed |
duke@435 | 228 | // by the factor |
duke@435 | 229 | // |
duke@435 | 230 | // average-interval-between-major-gc * AdaptiveSizeMajorGCDecayTimeScale / |
duke@435 | 231 | // time-since-last-major-gc |
duke@435 | 232 | // |
duke@435 | 233 | // if the average-interval-between-major-gc * AdaptiveSizeMajorGCDecayTimeScale |
duke@435 | 234 | // is less than time-since-last-major-gc. |
duke@435 | 235 | // |
duke@435 | 236 | // In cases where there are initial major gc's that |
duke@435 | 237 | // are of a relatively high cost but no later major |
duke@435 | 238 | // gc's, the total gc cost can remain high because |
duke@435 | 239 | // the major gc cost remains unchanged (since there are no major |
duke@435 | 240 | // gc's). In such a situation the value of the unchanging |
duke@435 | 241 | // major gc cost can keep the mutator throughput below |
duke@435 | 242 | // the goal when in fact the major gc cost is becoming diminishingly |
duke@435 | 243 | // small. Use the decaying gc cost only to decide whether to |
duke@435 | 244 | // adjust for throughput. Using it also to determine the adjustment |
duke@435 | 245 | // to be made for throughput also seems reasonable but there is |
duke@435 | 246 | // no test case to use to decide if it is the right thing to do |
duke@435 | 247 | // don't do it yet. |
duke@435 | 248 | |
duke@435 | 249 | double AdaptiveSizePolicy::decaying_gc_cost() const { |
duke@435 | 250 | double decayed_major_gc_cost = major_gc_cost(); |
duke@435 | 251 | double avg_major_interval = major_gc_interval_average_for_decay(); |
duke@435 | 252 | if (UseAdaptiveSizeDecayMajorGCCost && |
duke@435 | 253 | (AdaptiveSizeMajorGCDecayTimeScale > 0) && |
duke@435 | 254 | (avg_major_interval > 0.00)) { |
duke@435 | 255 | double time_since_last_major_gc = time_since_major_gc(); |
duke@435 | 256 | |
duke@435 | 257 | // Decay the major gc cost? |
duke@435 | 258 | if (time_since_last_major_gc > |
duke@435 | 259 | ((double) AdaptiveSizeMajorGCDecayTimeScale) * avg_major_interval) { |
duke@435 | 260 | |
duke@435 | 261 | // Decay using the time-since-last-major-gc |
duke@435 | 262 | decayed_major_gc_cost = decaying_major_gc_cost(); |
duke@435 | 263 | if (PrintGCDetails && Verbose) { |
duke@435 | 264 | gclog_or_tty->print_cr("\ndecaying_gc_cost: major interval average:" |
duke@435 | 265 | " %f time since last major gc: %f", |
duke@435 | 266 | avg_major_interval, time_since_last_major_gc); |
duke@435 | 267 | gclog_or_tty->print_cr(" major gc cost: %f decayed major gc cost: %f", |
duke@435 | 268 | major_gc_cost(), decayed_major_gc_cost); |
duke@435 | 269 | } |
duke@435 | 270 | } |
duke@435 | 271 | } |
duke@435 | 272 | double result = MIN2(1.0, decayed_major_gc_cost + minor_gc_cost()); |
duke@435 | 273 | return result; |
duke@435 | 274 | } |
duke@435 | 275 | |
duke@435 | 276 | |
duke@435 | 277 | void AdaptiveSizePolicy::clear_generation_free_space_flags() { |
duke@435 | 278 | set_change_young_gen_for_min_pauses(0); |
duke@435 | 279 | set_change_old_gen_for_maj_pauses(0); |
duke@435 | 280 | |
duke@435 | 281 | set_change_old_gen_for_throughput(0); |
duke@435 | 282 | set_change_young_gen_for_throughput(0); |
duke@435 | 283 | set_decrease_for_footprint(0); |
duke@435 | 284 | set_decide_at_full_gc(0); |
duke@435 | 285 | } |
duke@435 | 286 | |
jmasa@1822 | 287 | void AdaptiveSizePolicy::check_gc_overhead_limit( |
jmasa@1822 | 288 | size_t young_live, |
jmasa@1822 | 289 | size_t eden_live, |
jmasa@1822 | 290 | size_t max_old_gen_size, |
jmasa@1822 | 291 | size_t max_eden_size, |
jmasa@1822 | 292 | bool is_full_gc, |
jmasa@1822 | 293 | GCCause::Cause gc_cause, |
jmasa@1822 | 294 | CollectorPolicy* collector_policy) { |
jmasa@1822 | 295 | |
jmasa@1822 | 296 | // Ignore explicit GC's. Exiting here does not set the flag and |
jmasa@1822 | 297 | // does not reset the count. Updating of the averages for system |
jmasa@1822 | 298 | // GC's is still controlled by UseAdaptiveSizePolicyWithSystemGC. |
jmasa@1822 | 299 | if (GCCause::is_user_requested_gc(gc_cause) || |
jmasa@1822 | 300 | GCCause::is_serviceability_requested_gc(gc_cause)) { |
jmasa@1822 | 301 | return; |
jmasa@1822 | 302 | } |
jmasa@1822 | 303 | // eden_limit is the upper limit on the size of eden based on |
jmasa@1822 | 304 | // the maximum size of the young generation and the sizes |
jmasa@1822 | 305 | // of the survivor space. |
jmasa@1822 | 306 | // The question being asked is whether the gc costs are high |
jmasa@1822 | 307 | // and the space being recovered by a collection is low. |
jmasa@1822 | 308 | // free_in_young_gen is the free space in the young generation |
jmasa@1822 | 309 | // after a collection and promo_live is the free space in the old |
jmasa@1822 | 310 | // generation after a collection. |
jmasa@1822 | 311 | // |
jmasa@1822 | 312 | // Use the minimum of the current value of the live in the |
jmasa@1822 | 313 | // young gen or the average of the live in the young gen. |
jmasa@1822 | 314 | // If the current value drops quickly, that should be taken |
jmasa@1822 | 315 | // into account (i.e., don't trigger if the amount of free |
jmasa@1822 | 316 | // space has suddenly jumped up). If the current is much |
jmasa@1822 | 317 | // higher than the average, use the average since it represents |
jmasa@1822 | 318 | // the longer term behavor. |
jmasa@1822 | 319 | const size_t live_in_eden = |
jmasa@1822 | 320 | MIN2(eden_live, (size_t) avg_eden_live()->average()); |
jmasa@1822 | 321 | const size_t free_in_eden = max_eden_size > live_in_eden ? |
jmasa@1822 | 322 | max_eden_size - live_in_eden : 0; |
jmasa@1822 | 323 | const size_t free_in_old_gen = (size_t)(max_old_gen_size - avg_old_live()->average()); |
jmasa@1822 | 324 | const size_t total_free_limit = free_in_old_gen + free_in_eden; |
jmasa@1822 | 325 | const size_t total_mem = max_old_gen_size + max_eden_size; |
jmasa@1822 | 326 | const double mem_free_limit = total_mem * (GCHeapFreeLimit/100.0); |
jmasa@1822 | 327 | const double mem_free_old_limit = max_old_gen_size * (GCHeapFreeLimit/100.0); |
jmasa@1822 | 328 | const double mem_free_eden_limit = max_eden_size * (GCHeapFreeLimit/100.0); |
jmasa@1822 | 329 | const double gc_cost_limit = GCTimeLimit/100.0; |
jmasa@1822 | 330 | size_t promo_limit = (size_t)(max_old_gen_size - avg_old_live()->average()); |
jmasa@1822 | 331 | // But don't force a promo size below the current promo size. Otherwise, |
jmasa@1822 | 332 | // the promo size will shrink for no good reason. |
jmasa@1822 | 333 | promo_limit = MAX2(promo_limit, _promo_size); |
jmasa@1822 | 334 | |
jmasa@1822 | 335 | |
jmasa@1822 | 336 | if (PrintAdaptiveSizePolicy && (Verbose || |
jmasa@1822 | 337 | (free_in_old_gen < (size_t) mem_free_old_limit && |
jmasa@1822 | 338 | free_in_eden < (size_t) mem_free_eden_limit))) { |
jmasa@1822 | 339 | gclog_or_tty->print_cr( |
jmasa@1822 | 340 | "PSAdaptiveSizePolicy::compute_generation_free_space limits:" |
jmasa@1822 | 341 | " promo_limit: " SIZE_FORMAT |
jmasa@1822 | 342 | " max_eden_size: " SIZE_FORMAT |
jmasa@1822 | 343 | " total_free_limit: " SIZE_FORMAT |
jmasa@1822 | 344 | " max_old_gen_size: " SIZE_FORMAT |
jmasa@1822 | 345 | " max_eden_size: " SIZE_FORMAT |
jmasa@1822 | 346 | " mem_free_limit: " SIZE_FORMAT, |
jmasa@1822 | 347 | promo_limit, max_eden_size, total_free_limit, |
jmasa@1822 | 348 | max_old_gen_size, max_eden_size, |
jmasa@1822 | 349 | (size_t) mem_free_limit); |
jmasa@1822 | 350 | } |
jmasa@1822 | 351 | |
jmasa@1822 | 352 | bool print_gc_overhead_limit_would_be_exceeded = false; |
jmasa@1822 | 353 | if (is_full_gc) { |
jmasa@1822 | 354 | if (gc_cost() > gc_cost_limit && |
jmasa@1822 | 355 | free_in_old_gen < (size_t) mem_free_old_limit && |
jmasa@1822 | 356 | free_in_eden < (size_t) mem_free_eden_limit) { |
jmasa@1822 | 357 | // Collections, on average, are taking too much time, and |
jmasa@1822 | 358 | // gc_cost() > gc_cost_limit |
jmasa@1822 | 359 | // we have too little space available after a full gc. |
jmasa@1822 | 360 | // total_free_limit < mem_free_limit |
jmasa@1822 | 361 | // where |
jmasa@1822 | 362 | // total_free_limit is the free space available in |
jmasa@1822 | 363 | // both generations |
jmasa@1822 | 364 | // total_mem is the total space available for allocation |
jmasa@1822 | 365 | // in both generations (survivor spaces are not included |
jmasa@1822 | 366 | // just as they are not included in eden_limit). |
jmasa@1822 | 367 | // mem_free_limit is a fraction of total_mem judged to be an |
jmasa@1822 | 368 | // acceptable amount that is still unused. |
jmasa@1822 | 369 | // The heap can ask for the value of this variable when deciding |
jmasa@1822 | 370 | // whether to thrown an OutOfMemory error. |
jmasa@1822 | 371 | // Note that the gc time limit test only works for the collections |
jmasa@1822 | 372 | // of the young gen + tenured gen and not for collections of the |
jmasa@1822 | 373 | // permanent gen. That is because the calculation of the space |
jmasa@1822 | 374 | // freed by the collection is the free space in the young gen + |
jmasa@1822 | 375 | // tenured gen. |
jmasa@1822 | 376 | // At this point the GC overhead limit is being exceeded. |
jmasa@1822 | 377 | inc_gc_overhead_limit_count(); |
jmasa@1822 | 378 | if (UseGCOverheadLimit) { |
jmasa@1822 | 379 | if (gc_overhead_limit_count() >= |
jmasa@1822 | 380 | AdaptiveSizePolicyGCTimeLimitThreshold){ |
jmasa@1822 | 381 | // All conditions have been met for throwing an out-of-memory |
jmasa@1822 | 382 | set_gc_overhead_limit_exceeded(true); |
jmasa@1822 | 383 | // Avoid consecutive OOM due to the gc time limit by resetting |
jmasa@1822 | 384 | // the counter. |
jmasa@1822 | 385 | reset_gc_overhead_limit_count(); |
jmasa@1822 | 386 | } else { |
jmasa@1822 | 387 | // The required consecutive collections which exceed the |
jmasa@1822 | 388 | // GC time limit may or may not have been reached. We |
jmasa@1822 | 389 | // are approaching that condition and so as not to |
jmasa@1822 | 390 | // throw an out-of-memory before all SoftRef's have been |
jmasa@1822 | 391 | // cleared, set _should_clear_all_soft_refs in CollectorPolicy. |
jmasa@1822 | 392 | // The clearing will be done on the next GC. |
jmasa@1822 | 393 | bool near_limit = gc_overhead_limit_near(); |
jmasa@1822 | 394 | if (near_limit) { |
jmasa@1822 | 395 | collector_policy->set_should_clear_all_soft_refs(true); |
jmasa@1822 | 396 | if (PrintGCDetails && Verbose) { |
jmasa@1822 | 397 | gclog_or_tty->print_cr(" Nearing GC overhead limit, " |
jmasa@1822 | 398 | "will be clearing all SoftReference"); |
jmasa@1822 | 399 | } |
jmasa@1822 | 400 | } |
jmasa@1822 | 401 | } |
jmasa@1822 | 402 | } |
jmasa@1822 | 403 | // Set this even when the overhead limit will not |
jmasa@1822 | 404 | // cause an out-of-memory. Diagnostic message indicating |
jmasa@1822 | 405 | // that the overhead limit is being exceeded is sometimes |
jmasa@1822 | 406 | // printed. |
jmasa@1822 | 407 | print_gc_overhead_limit_would_be_exceeded = true; |
jmasa@1822 | 408 | |
jmasa@1822 | 409 | } else { |
jmasa@1822 | 410 | // Did not exceed overhead limits |
jmasa@1822 | 411 | reset_gc_overhead_limit_count(); |
jmasa@1822 | 412 | } |
jmasa@1822 | 413 | } |
jmasa@1822 | 414 | |
jmasa@1822 | 415 | if (UseGCOverheadLimit && PrintGCDetails && Verbose) { |
jmasa@1822 | 416 | if (gc_overhead_limit_exceeded()) { |
jmasa@1822 | 417 | gclog_or_tty->print_cr(" GC is exceeding overhead limit " |
jmasa@1822 | 418 | "of %d%%", GCTimeLimit); |
jmasa@1822 | 419 | reset_gc_overhead_limit_count(); |
jmasa@1822 | 420 | } else if (print_gc_overhead_limit_would_be_exceeded) { |
jmasa@1822 | 421 | assert(gc_overhead_limit_count() > 0, "Should not be printing"); |
jmasa@1822 | 422 | gclog_or_tty->print_cr(" GC would exceed overhead limit " |
jmasa@1822 | 423 | "of %d%% %d consecutive time(s)", |
jmasa@1822 | 424 | GCTimeLimit, gc_overhead_limit_count()); |
jmasa@1822 | 425 | } |
jmasa@1822 | 426 | } |
jmasa@1822 | 427 | } |
duke@435 | 428 | // Printing |
duke@435 | 429 | |
duke@435 | 430 | bool AdaptiveSizePolicy::print_adaptive_size_policy_on(outputStream* st) const { |
duke@435 | 431 | |
duke@435 | 432 | // Should only be used with adaptive size policy turned on. |
duke@435 | 433 | // Otherwise, there may be variables that are undefined. |
duke@435 | 434 | if (!UseAdaptiveSizePolicy) return false; |
duke@435 | 435 | |
duke@435 | 436 | // Print goal for which action is needed. |
duke@435 | 437 | char* action = NULL; |
duke@435 | 438 | bool change_for_pause = false; |
duke@435 | 439 | if ((change_old_gen_for_maj_pauses() == |
duke@435 | 440 | decrease_old_gen_for_maj_pauses_true) || |
duke@435 | 441 | (change_young_gen_for_min_pauses() == |
duke@435 | 442 | decrease_young_gen_for_min_pauses_true)) { |
duke@435 | 443 | action = (char*) " *** pause time goal ***"; |
duke@435 | 444 | change_for_pause = true; |
duke@435 | 445 | } else if ((change_old_gen_for_throughput() == |
duke@435 | 446 | increase_old_gen_for_throughput_true) || |
duke@435 | 447 | (change_young_gen_for_throughput() == |
duke@435 | 448 | increase_young_gen_for_througput_true)) { |
duke@435 | 449 | action = (char*) " *** throughput goal ***"; |
duke@435 | 450 | } else if (decrease_for_footprint()) { |
duke@435 | 451 | action = (char*) " *** reduced footprint ***"; |
duke@435 | 452 | } else { |
duke@435 | 453 | // No actions were taken. This can legitimately be the |
duke@435 | 454 | // situation if not enough data has been gathered to make |
duke@435 | 455 | // decisions. |
duke@435 | 456 | return false; |
duke@435 | 457 | } |
duke@435 | 458 | |
duke@435 | 459 | // Pauses |
duke@435 | 460 | // Currently the size of the old gen is only adjusted to |
duke@435 | 461 | // change the major pause times. |
duke@435 | 462 | char* young_gen_action = NULL; |
duke@435 | 463 | char* tenured_gen_action = NULL; |
duke@435 | 464 | |
duke@435 | 465 | char* shrink_msg = (char*) "(attempted to shrink)"; |
duke@435 | 466 | char* grow_msg = (char*) "(attempted to grow)"; |
duke@435 | 467 | char* no_change_msg = (char*) "(no change)"; |
duke@435 | 468 | if (change_young_gen_for_min_pauses() == |
duke@435 | 469 | decrease_young_gen_for_min_pauses_true) { |
duke@435 | 470 | young_gen_action = shrink_msg; |
duke@435 | 471 | } else if (change_for_pause) { |
duke@435 | 472 | young_gen_action = no_change_msg; |
duke@435 | 473 | } |
duke@435 | 474 | |
duke@435 | 475 | if (change_old_gen_for_maj_pauses() == decrease_old_gen_for_maj_pauses_true) { |
duke@435 | 476 | tenured_gen_action = shrink_msg; |
duke@435 | 477 | } else if (change_for_pause) { |
duke@435 | 478 | tenured_gen_action = no_change_msg; |
duke@435 | 479 | } |
duke@435 | 480 | |
duke@435 | 481 | // Throughput |
duke@435 | 482 | if (change_old_gen_for_throughput() == increase_old_gen_for_throughput_true) { |
duke@435 | 483 | assert(change_young_gen_for_throughput() == |
duke@435 | 484 | increase_young_gen_for_througput_true, |
duke@435 | 485 | "Both generations should be growing"); |
duke@435 | 486 | young_gen_action = grow_msg; |
duke@435 | 487 | tenured_gen_action = grow_msg; |
duke@435 | 488 | } else if (change_young_gen_for_throughput() == |
duke@435 | 489 | increase_young_gen_for_througput_true) { |
duke@435 | 490 | // Only the young generation may grow at start up (before |
duke@435 | 491 | // enough full collections have been done to grow the old generation). |
duke@435 | 492 | young_gen_action = grow_msg; |
duke@435 | 493 | tenured_gen_action = no_change_msg; |
duke@435 | 494 | } |
duke@435 | 495 | |
duke@435 | 496 | // Minimum footprint |
duke@435 | 497 | if (decrease_for_footprint() != 0) { |
duke@435 | 498 | young_gen_action = shrink_msg; |
duke@435 | 499 | tenured_gen_action = shrink_msg; |
duke@435 | 500 | } |
duke@435 | 501 | |
duke@435 | 502 | st->print_cr(" UseAdaptiveSizePolicy actions to meet %s", action); |
duke@435 | 503 | st->print_cr(" GC overhead (%%)"); |
duke@435 | 504 | st->print_cr(" Young generation: %7.2f\t %s", |
duke@435 | 505 | 100.0 * avg_minor_gc_cost()->average(), |
duke@435 | 506 | young_gen_action); |
duke@435 | 507 | st->print_cr(" Tenured generation: %7.2f\t %s", |
duke@435 | 508 | 100.0 * avg_major_gc_cost()->average(), |
duke@435 | 509 | tenured_gen_action); |
duke@435 | 510 | return true; |
duke@435 | 511 | } |
duke@435 | 512 | |
duke@435 | 513 | bool AdaptiveSizePolicy::print_adaptive_size_policy_on( |
duke@435 | 514 | outputStream* st, |
duke@435 | 515 | int tenuring_threshold_arg) const { |
duke@435 | 516 | if (!AdaptiveSizePolicy::print_adaptive_size_policy_on(st)) { |
duke@435 | 517 | return false; |
duke@435 | 518 | } |
duke@435 | 519 | |
duke@435 | 520 | // Tenuring threshold |
duke@435 | 521 | bool tenuring_threshold_changed = true; |
duke@435 | 522 | if (decrement_tenuring_threshold_for_survivor_limit()) { |
duke@435 | 523 | st->print(" Tenuring threshold: (attempted to decrease to avoid" |
duke@435 | 524 | " survivor space overflow) = "); |
duke@435 | 525 | } else if (decrement_tenuring_threshold_for_gc_cost()) { |
duke@435 | 526 | st->print(" Tenuring threshold: (attempted to decrease to balance" |
duke@435 | 527 | " GC costs) = "); |
duke@435 | 528 | } else if (increment_tenuring_threshold_for_gc_cost()) { |
duke@435 | 529 | st->print(" Tenuring threshold: (attempted to increase to balance" |
duke@435 | 530 | " GC costs) = "); |
duke@435 | 531 | } else { |
duke@435 | 532 | tenuring_threshold_changed = false; |
duke@435 | 533 | assert(!tenuring_threshold_change(), "(no change was attempted)"); |
duke@435 | 534 | } |
duke@435 | 535 | if (tenuring_threshold_changed) { |
duke@435 | 536 | st->print_cr("%d", tenuring_threshold_arg); |
duke@435 | 537 | } |
duke@435 | 538 | return true; |
duke@435 | 539 | } |