src/share/vm/gc_implementation/parallelScavenge/psAdaptiveSizePolicy.cpp

Thu, 22 Sep 2011 10:57:37 -0700

author
johnc
date
Thu, 22 Sep 2011 10:57:37 -0700
changeset 3175
4dfb2df418f2
parent 2314
f95d63e2154a
child 4037
da91efe96a93
permissions
-rw-r--r--

6484982: G1: process references during evacuation pauses
Summary: G1 now uses two reference processors - one is used by concurrent marking and the other is used by STW GCs (both full and incremental evacuation pauses). In an evacuation pause, the reference processor is embedded into the closures used to scan objects. Doing so causes causes reference objects to be 'discovered' by the reference processor. At the end of the evacuation pause, these discovered reference objects are processed - preserving (and copying) referent objects (and their reachable graphs) as appropriate.
Reviewed-by: ysr, jwilhelm, brutisso, stefank, tonyp

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

mercurial