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