Path: blob/master/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp
41149 views
/*1* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "gc/parallel/parallelScavengeHeap.hpp"26#include "gc/parallel/psAdaptiveSizePolicy.hpp"27#include "gc/parallel/psGCAdaptivePolicyCounters.hpp"28#include "gc/parallel/psScavenge.hpp"29#include "gc/shared/gcCause.hpp"30#include "gc/shared/gcUtil.inline.hpp"31#include "gc/shared/gcPolicyCounters.hpp"32#include "logging/log.hpp"33#include "runtime/timer.hpp"34#include "utilities/align.hpp"3536#include <math.h>3738PSAdaptiveSizePolicy::PSAdaptiveSizePolicy(size_t init_eden_size,39size_t init_promo_size,40size_t init_survivor_size,41size_t space_alignment,42double gc_pause_goal_sec,43double gc_minor_pause_goal_sec,44uint gc_cost_ratio) :45AdaptiveSizePolicy(init_eden_size,46init_promo_size,47init_survivor_size,48gc_pause_goal_sec,49gc_cost_ratio),50_avg_major_pause(new AdaptivePaddedAverage(AdaptiveTimeWeight, PausePadding)),51_avg_base_footprint(new AdaptiveWeightedAverage(AdaptiveSizePolicyWeight)),52_gc_stats(),53_collection_cost_margin_fraction(AdaptiveSizePolicyCollectionCostMargin / 100.0),54_major_pause_old_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)),55_major_pause_young_estimator(new LinearLeastSquareFit(AdaptiveSizePolicyWeight)),56_latest_major_mutator_interval_seconds(0),57_space_alignment(space_alignment),58_gc_minor_pause_goal_sec(gc_minor_pause_goal_sec),59_live_at_last_full_gc(init_promo_size),60_change_old_gen_for_min_pauses(0),61_change_young_gen_for_maj_pauses(0),62_young_gen_size_increment_supplement(YoungGenerationSizeSupplement),63_old_gen_size_increment_supplement(TenuredGenerationSizeSupplement)64{65// Start the timers66_major_timer.start();67}6869size_t PSAdaptiveSizePolicy::calculate_free_based_on_live(size_t live, uintx ratio_as_percentage) {70// We want to calculate how much free memory there can be based on the71// amount of live data currently in the old gen. Using the formula:72// ratio * (free + live) = free73// Some equation solving later we get:74// free = (live * ratio) / (1 - ratio)7576const double ratio = ratio_as_percentage / 100.0;77const double ratio_inverse = 1.0 - ratio;78const double tmp = live * ratio;79size_t free = (size_t)(tmp / ratio_inverse);8081return free;82}8384size_t PSAdaptiveSizePolicy::calculated_old_free_size_in_bytes() const {85size_t free_size = (size_t)(_promo_size + avg_promoted()->padded_average());86size_t live = ParallelScavengeHeap::heap()->old_gen()->used_in_bytes();8788if (MinHeapFreeRatio != 0) {89size_t min_free = calculate_free_based_on_live(live, MinHeapFreeRatio);90free_size = MAX2(free_size, min_free);91}9293if (MaxHeapFreeRatio != 100) {94size_t max_free = calculate_free_based_on_live(live, MaxHeapFreeRatio);95free_size = MIN2(max_free, free_size);96}9798return free_size;99}100101void PSAdaptiveSizePolicy::major_collection_begin() {102// Update the interval time103_major_timer.stop();104// Save most recent collection time105_latest_major_mutator_interval_seconds = _major_timer.seconds();106_major_timer.reset();107_major_timer.start();108}109110void PSAdaptiveSizePolicy::update_minor_pause_old_estimator(111double minor_pause_in_ms) {112double promo_size_in_mbytes = ((double)_promo_size)/((double)M);113_minor_pause_old_estimator->update(promo_size_in_mbytes,114minor_pause_in_ms);115}116117void PSAdaptiveSizePolicy::major_collection_end(size_t amount_live,118GCCause::Cause gc_cause) {119// Update the pause time.120_major_timer.stop();121122if (should_update_promo_stats(gc_cause)) {123double major_pause_in_seconds = _major_timer.seconds();124double major_pause_in_ms = major_pause_in_seconds * MILLIUNITS;125126// Sample for performance counter127_avg_major_pause->sample(major_pause_in_seconds);128129// Cost of collection (unit-less)130double collection_cost = 0.0;131if ((_latest_major_mutator_interval_seconds > 0.0) &&132(major_pause_in_seconds > 0.0)) {133double interval_in_seconds =134_latest_major_mutator_interval_seconds + major_pause_in_seconds;135collection_cost =136major_pause_in_seconds / interval_in_seconds;137avg_major_gc_cost()->sample(collection_cost);138139// Sample for performance counter140_avg_major_interval->sample(interval_in_seconds);141}142143// Calculate variables used to estimate pause time vs. gen sizes144double eden_size_in_mbytes = ((double)_eden_size)/((double)M);145double promo_size_in_mbytes = ((double)_promo_size)/((double)M);146_major_pause_old_estimator->update(promo_size_in_mbytes,147major_pause_in_ms);148_major_pause_young_estimator->update(eden_size_in_mbytes,149major_pause_in_ms);150151log_trace(gc, ergo)("psAdaptiveSizePolicy::major_collection_end: major gc cost: %f average: %f",152collection_cost,avg_major_gc_cost()->average());153log_trace(gc, ergo)(" major pause: %f major period %f",154major_pause_in_ms, _latest_major_mutator_interval_seconds * MILLIUNITS);155156// Calculate variable used to estimate collection cost vs. gen sizes157assert(collection_cost >= 0.0, "Expected to be non-negative");158_major_collection_estimator->update(promo_size_in_mbytes,159collection_cost);160}161162// Update the amount live at the end of a full GC163_live_at_last_full_gc = amount_live;164165// Interval times use this timer to measure the interval that166// the mutator runs. Reset after the GC pause has been measured.167_major_timer.reset();168_major_timer.start();169}170171// If the remaining free space in the old generation is less that172// that expected to be needed by the next collection, do a full173// collection now.174bool PSAdaptiveSizePolicy::should_full_GC(size_t old_free_in_bytes) {175176// A similar test is done in the scavenge's should_attempt_scavenge(). If177// this is changed, decide if that test should also be changed.178bool result = padded_average_promoted_in_bytes() > (float) old_free_in_bytes;179log_trace(gc, ergo)("%s after scavenge average_promoted " SIZE_FORMAT " padded_average_promoted " SIZE_FORMAT " free in old gen " SIZE_FORMAT,180result ? "Full" : "No full",181(size_t) average_promoted_in_bytes(),182(size_t) padded_average_promoted_in_bytes(),183old_free_in_bytes);184return result;185}186187void PSAdaptiveSizePolicy::clear_generation_free_space_flags() {188189AdaptiveSizePolicy::clear_generation_free_space_flags();190191set_change_old_gen_for_min_pauses(0);192193set_change_young_gen_for_maj_pauses(0);194}195196// If this is not a full GC, only test and modify the young generation.197198void PSAdaptiveSizePolicy::compute_generations_free_space(199size_t young_live,200size_t eden_live,201size_t old_live,202size_t cur_eden,203size_t max_old_gen_size,204size_t max_eden_size,205bool is_full_gc) {206compute_eden_space_size(young_live,207eden_live,208cur_eden,209max_eden_size,210is_full_gc);211212compute_old_gen_free_space(old_live,213cur_eden,214max_old_gen_size,215is_full_gc);216}217218void PSAdaptiveSizePolicy::compute_eden_space_size(219size_t young_live,220size_t eden_live,221size_t cur_eden,222size_t max_eden_size,223bool is_full_gc) {224225// Update statistics226// Time statistics are updated as we go, update footprint stats here227_avg_base_footprint->sample(BaseFootPrintEstimate);228avg_young_live()->sample(young_live);229avg_eden_live()->sample(eden_live);230231// This code used to return if the policy was not ready , i.e.,232// policy_is_ready() returning false. The intent was that233// decisions below needed major collection times and so could234// not be made before two major collections. A consequence was235// adjustments to the young generation were not done until after236// two major collections even if the minor collections times237// exceeded the requested goals. Now let the young generation238// adjust for the minor collection times. Major collection times239// will be zero for the first collection and will naturally be240// ignored. Tenured generation adjustments are only made at the241// full collections so until the second major collection has242// been reached, no tenured generation adjustments will be made.243244// Until we know better, desired promotion size uses the last calculation245size_t desired_promo_size = _promo_size;246247// Start eden at the current value. The desired value that is stored248// in _eden_size is not bounded by constraints of the heap and can249// run away.250//251// As expected setting desired_eden_size to the current252// value of desired_eden_size as a starting point253// caused desired_eden_size to grow way too large and caused254// an overflow down stream. It may have improved performance in255// some case but is dangerous.256size_t desired_eden_size = cur_eden;257258// Cache some values. There's a bit of work getting these, so259// we might save a little time.260const double major_cost = major_gc_cost();261const double minor_cost = minor_gc_cost();262263// This method sets the desired eden size. That plus the264// desired survivor space sizes sets the desired young generation265// size. This methods does not know what the desired survivor266// size is but expects that other policy will attempt to make267// the survivor sizes compatible with the live data in the268// young generation. This limit is an estimate of the space left269// in the young generation after the survivor spaces have been270// subtracted out.271size_t eden_limit = max_eden_size;272273const double gc_cost_limit = GCTimeLimit / 100.0;274275// Which way should we go?276// if pause requirement is not met277// adjust size of any generation with average paus exceeding278// the pause limit. Adjust one pause at a time (the larger)279// and only make adjustments for the major pause at full collections.280// else if throughput requirement not met281// adjust the size of the generation with larger gc time. Only282// adjust one generation at a time.283// else284// adjust down the total heap size. Adjust down the larger of the285// generations.286287// Add some checks for a threshold for a change. For example,288// a change less than the necessary alignment is probably not worth289// attempting.290291292if ((_avg_minor_pause->padded_average() > gc_pause_goal_sec()) ||293(_avg_major_pause->padded_average() > gc_pause_goal_sec())) {294//295// Check pauses296//297// Make changes only to affect one of the pauses (the larger)298// at a time.299adjust_eden_for_pause_time(is_full_gc, &desired_promo_size, &desired_eden_size);300301} else if (_avg_minor_pause->padded_average() > gc_minor_pause_goal_sec()) {302// Adjust only for the minor pause time goal303adjust_eden_for_minor_pause_time(is_full_gc, &desired_eden_size);304305} else if(adjusted_mutator_cost() < _throughput_goal) {306// This branch used to require that (mutator_cost() > 0.0 in 1.4.2.307// This sometimes resulted in skipping to the minimize footprint308// code. Change this to try and reduce GC time if mutator time is309// negative for whatever reason. Or for future consideration,310// bail out of the code if mutator time is negative.311//312// Throughput313//314assert(major_cost >= 0.0, "major cost is < 0.0");315assert(minor_cost >= 0.0, "minor cost is < 0.0");316// Try to reduce the GC times.317adjust_eden_for_throughput(is_full_gc, &desired_eden_size);318319} else {320321// Be conservative about reducing the footprint.322// Do a minimum number of major collections first.323// Have reasonable averages for major and minor collections costs.324if (UseAdaptiveSizePolicyFootprintGoal &&325young_gen_policy_is_ready() &&326avg_major_gc_cost()->average() >= 0.0 &&327avg_minor_gc_cost()->average() >= 0.0) {328size_t desired_sum = desired_eden_size + desired_promo_size;329desired_eden_size = adjust_eden_for_footprint(desired_eden_size, desired_sum);330}331}332333// Note we make the same tests as in the code block below; the code334// seems a little easier to read with the printing in another block.335if (desired_eden_size > eden_limit) {336log_debug(gc, ergo)(337"PSAdaptiveSizePolicy::compute_eden_space_size limits:"338" desired_eden_size: " SIZE_FORMAT339" old_eden_size: " SIZE_FORMAT340" eden_limit: " SIZE_FORMAT341" cur_eden: " SIZE_FORMAT342" max_eden_size: " SIZE_FORMAT343" avg_young_live: " SIZE_FORMAT,344desired_eden_size, _eden_size, eden_limit, cur_eden,345max_eden_size, (size_t)avg_young_live()->average());346}347if (gc_cost() > gc_cost_limit) {348log_debug(gc, ergo)(349"PSAdaptiveSizePolicy::compute_eden_space_size: gc time limit"350" gc_cost: %f "351" GCTimeLimit: " UINTX_FORMAT,352gc_cost(), GCTimeLimit);353}354355// Align everything and make a final limit check356desired_eden_size = align_up(desired_eden_size, _space_alignment);357desired_eden_size = MAX2(desired_eden_size, _space_alignment);358359eden_limit = align_down(eden_limit, _space_alignment);360361// And one last limit check, now that we've aligned things.362if (desired_eden_size > eden_limit) {363// If the policy says to get a larger eden but364// is hitting the limit, don't decrease eden.365// This can lead to a general drifting down of the366// eden size. Let the tenuring calculation push more367// into the old gen.368desired_eden_size = MAX2(eden_limit, cur_eden);369}370371log_debug(gc, ergo)("PSAdaptiveSizePolicy::compute_eden_space_size: costs minor_time: %f major_cost: %f mutator_cost: %f throughput_goal: %f",372minor_gc_cost(), major_gc_cost(), mutator_cost(), _throughput_goal);373374log_trace(gc, ergo)("Minor_pause: %f major_pause: %f minor_interval: %f major_interval: %fpause_goal: %f",375_avg_minor_pause->padded_average(),376_avg_major_pause->padded_average(),377_avg_minor_interval->average(),378_avg_major_interval->average(),379gc_pause_goal_sec());380381log_debug(gc, ergo)("Live_space: " SIZE_FORMAT " free_space: " SIZE_FORMAT,382live_space(), free_space());383384log_trace(gc, ergo)("Base_footprint: " SIZE_FORMAT " avg_young_live: " SIZE_FORMAT " avg_old_live: " SIZE_FORMAT,385(size_t)_avg_base_footprint->average(),386(size_t)avg_young_live()->average(),387(size_t)avg_old_live()->average());388389log_debug(gc, ergo)("Old eden_size: " SIZE_FORMAT " desired_eden_size: " SIZE_FORMAT,390_eden_size, desired_eden_size);391392set_eden_size(desired_eden_size);393}394395void PSAdaptiveSizePolicy::compute_old_gen_free_space(396size_t old_live,397size_t cur_eden,398size_t max_old_gen_size,399bool is_full_gc) {400401// Update statistics402// Time statistics are updated as we go, update footprint stats here403if (is_full_gc) {404// old_live is only accurate after a full gc405avg_old_live()->sample(old_live);406}407408// This code used to return if the policy was not ready , i.e.,409// policy_is_ready() returning false. The intent was that410// decisions below needed major collection times and so could411// not be made before two major collections. A consequence was412// adjustments to the young generation were not done until after413// two major collections even if the minor collections times414// exceeded the requested goals. Now let the young generation415// adjust for the minor collection times. Major collection times416// will be zero for the first collection and will naturally be417// ignored. Tenured generation adjustments are only made at the418// full collections so until the second major collection has419// been reached, no tenured generation adjustments will be made.420421// Until we know better, desired promotion size uses the last calculation422size_t desired_promo_size = _promo_size;423424// Start eden at the current value. The desired value that is stored425// in _eden_size is not bounded by constraints of the heap and can426// run away.427//428// As expected setting desired_eden_size to the current429// value of desired_eden_size as a starting point430// caused desired_eden_size to grow way too large and caused431// an overflow down stream. It may have improved performance in432// some case but is dangerous.433size_t desired_eden_size = cur_eden;434435// Cache some values. There's a bit of work getting these, so436// we might save a little time.437const double major_cost = major_gc_cost();438const double minor_cost = minor_gc_cost();439440// Limits on our growth441size_t promo_limit = (size_t)(max_old_gen_size - avg_old_live()->average());442443// But don't force a promo size below the current promo size. Otherwise,444// the promo size will shrink for no good reason.445promo_limit = MAX2(promo_limit, _promo_size);446447const double gc_cost_limit = GCTimeLimit/100.0;448449// Which way should we go?450// if pause requirement is not met451// adjust size of any generation with average paus exceeding452// the pause limit. Adjust one pause at a time (the larger)453// and only make adjustments for the major pause at full collections.454// else if throughput requirement not met455// adjust the size of the generation with larger gc time. Only456// adjust one generation at a time.457// else458// adjust down the total heap size. Adjust down the larger of the459// generations.460461// Add some checks for a threshold for a change. For example,462// a change less than the necessary alignment is probably not worth463// attempting.464465if ((_avg_minor_pause->padded_average() > gc_pause_goal_sec()) ||466(_avg_major_pause->padded_average() > gc_pause_goal_sec())) {467//468// Check pauses469//470// Make changes only to affect one of the pauses (the larger)471// at a time.472if (is_full_gc) {473set_decide_at_full_gc(decide_at_full_gc_true);474adjust_promo_for_pause_time(is_full_gc, &desired_promo_size, &desired_eden_size);475}476} else if (adjusted_mutator_cost() < _throughput_goal) {477// This branch used to require that (mutator_cost() > 0.0 in 1.4.2.478// This sometimes resulted in skipping to the minimize footprint479// code. Change this to try and reduce GC time if mutator time is480// negative for whatever reason. Or for future consideration,481// bail out of the code if mutator time is negative.482//483// Throughput484//485assert(major_cost >= 0.0, "major cost is < 0.0");486assert(minor_cost >= 0.0, "minor cost is < 0.0");487// Try to reduce the GC times.488if (is_full_gc) {489set_decide_at_full_gc(decide_at_full_gc_true);490adjust_promo_for_throughput(is_full_gc, &desired_promo_size);491}492} else {493494// Be conservative about reducing the footprint.495// Do a minimum number of major collections first.496// Have reasonable averages for major and minor collections costs.497if (UseAdaptiveSizePolicyFootprintGoal &&498young_gen_policy_is_ready() &&499avg_major_gc_cost()->average() >= 0.0 &&500avg_minor_gc_cost()->average() >= 0.0) {501if (is_full_gc) {502set_decide_at_full_gc(decide_at_full_gc_true);503size_t desired_sum = desired_eden_size + desired_promo_size;504desired_promo_size = adjust_promo_for_footprint(desired_promo_size, desired_sum);505}506}507}508509// Note we make the same tests as in the code block below; the code510// seems a little easier to read with the printing in another block.511if (desired_promo_size > promo_limit) {512// "free_in_old_gen" was the original value for used for promo_limit513size_t free_in_old_gen = (size_t)(max_old_gen_size - avg_old_live()->average());514log_debug(gc, ergo)(515"PSAdaptiveSizePolicy::compute_old_gen_free_space limits:"516" desired_promo_size: " SIZE_FORMAT517" promo_limit: " SIZE_FORMAT518" free_in_old_gen: " SIZE_FORMAT519" max_old_gen_size: " SIZE_FORMAT520" avg_old_live: " SIZE_FORMAT,521desired_promo_size, promo_limit, free_in_old_gen,522max_old_gen_size, (size_t) avg_old_live()->average());523}524if (gc_cost() > gc_cost_limit) {525log_debug(gc, ergo)(526"PSAdaptiveSizePolicy::compute_old_gen_free_space: gc time limit"527" gc_cost: %f "528" GCTimeLimit: " UINTX_FORMAT,529gc_cost(), GCTimeLimit);530}531532// Align everything and make a final limit check533desired_promo_size = align_up(desired_promo_size, _space_alignment);534desired_promo_size = MAX2(desired_promo_size, _space_alignment);535536promo_limit = align_down(promo_limit, _space_alignment);537538// And one last limit check, now that we've aligned things.539desired_promo_size = MIN2(desired_promo_size, promo_limit);540541// Timing stats542log_debug(gc, ergo)("PSAdaptiveSizePolicy::compute_old_gen_free_space: costs minor_time: %f major_cost: %f mutator_cost: %f throughput_goal: %f",543minor_gc_cost(), major_gc_cost(), mutator_cost(), _throughput_goal);544545log_trace(gc, ergo)("Minor_pause: %f major_pause: %f minor_interval: %f major_interval: %f pause_goal: %f",546_avg_minor_pause->padded_average(),547_avg_major_pause->padded_average(),548_avg_minor_interval->average(),549_avg_major_interval->average(),550gc_pause_goal_sec());551552// Footprint stats553log_debug(gc, ergo)("Live_space: " SIZE_FORMAT " free_space: " SIZE_FORMAT,554live_space(), free_space());555556log_trace(gc, ergo)("Base_footprint: " SIZE_FORMAT " avg_young_live: " SIZE_FORMAT " avg_old_live: " SIZE_FORMAT,557(size_t)_avg_base_footprint->average(),558(size_t)avg_young_live()->average(),559(size_t)avg_old_live()->average());560561log_debug(gc, ergo)("Old promo_size: " SIZE_FORMAT " desired_promo_size: " SIZE_FORMAT,562_promo_size, desired_promo_size);563564set_promo_size(desired_promo_size);565}566567void PSAdaptiveSizePolicy::decay_supplemental_growth(bool is_full_gc) {568// Decay the supplemental increment? Decay the supplement growth569// factor even if it is not used. It is only meant to give a boost570// to the initial growth and if it is not used, then it was not571// needed.572if (is_full_gc) {573// Don't wait for the threshold value for the major collections. If574// here, the supplemental growth term was used and should decay.575if ((_avg_major_pause->count() % TenuredGenerationSizeSupplementDecay)576== 0) {577_old_gen_size_increment_supplement =578_old_gen_size_increment_supplement >> 1;579}580} else {581if ((_avg_minor_pause->count() >= AdaptiveSizePolicyReadyThreshold) &&582(_avg_minor_pause->count() % YoungGenerationSizeSupplementDecay) == 0) {583_young_gen_size_increment_supplement =584_young_gen_size_increment_supplement >> 1;585}586}587}588589void PSAdaptiveSizePolicy::adjust_eden_for_minor_pause_time(bool is_full_gc,590size_t* desired_eden_size_ptr) {591592// Adjust the young generation size to reduce pause time of593// of collections.594//595// The AdaptiveSizePolicyInitializingSteps test is not used596// here. It has not seemed to be needed but perhaps should597// be added for consistency.598if (minor_pause_young_estimator()->decrement_will_decrease()) {599// reduce eden size600set_change_young_gen_for_min_pauses(601decrease_young_gen_for_min_pauses_true);602*desired_eden_size_ptr = *desired_eden_size_ptr -603eden_decrement_aligned_down(*desired_eden_size_ptr);604} else {605// EXPERIMENTAL ADJUSTMENT606// Only record that the estimator indicated such an action.607// *desired_eden_size_ptr = *desired_eden_size_ptr + eden_heap_delta;608set_change_young_gen_for_min_pauses(609increase_young_gen_for_min_pauses_true);610}611}612613void PSAdaptiveSizePolicy::adjust_promo_for_pause_time(bool is_full_gc,614size_t* desired_promo_size_ptr,615size_t* desired_eden_size_ptr) {616617size_t promo_heap_delta = 0;618// Add some checks for a threshold for a change. For example,619// a change less than the required alignment is probably not worth620// attempting.621622if (_avg_minor_pause->padded_average() <= _avg_major_pause->padded_average() && is_full_gc) {623// Adjust for the major pause time only at full gc's because the624// affects of a change can only be seen at full gc's.625626// Reduce old generation size to reduce pause?627if (major_pause_old_estimator()->decrement_will_decrease()) {628// reduce old generation size629set_change_old_gen_for_maj_pauses(decrease_old_gen_for_maj_pauses_true);630promo_heap_delta = promo_decrement_aligned_down(*desired_promo_size_ptr);631*desired_promo_size_ptr = _promo_size - promo_heap_delta;632} else {633// EXPERIMENTAL ADJUSTMENT634// Only record that the estimator indicated such an action.635// *desired_promo_size_ptr = _promo_size +636// promo_increment_aligned_up(*desired_promo_size_ptr);637set_change_old_gen_for_maj_pauses(increase_old_gen_for_maj_pauses_true);638}639}640641log_trace(gc, ergo)(642"PSAdaptiveSizePolicy::adjust_promo_for_pause_time "643"adjusting gen sizes for major pause (avg %f goal %f). "644"desired_promo_size " SIZE_FORMAT " promo delta " SIZE_FORMAT,645_avg_major_pause->average(), gc_pause_goal_sec(),646*desired_promo_size_ptr, promo_heap_delta);647}648649void PSAdaptiveSizePolicy::adjust_eden_for_pause_time(bool is_full_gc,650size_t* desired_promo_size_ptr,651size_t* desired_eden_size_ptr) {652653size_t eden_heap_delta = 0;654// Add some checks for a threshold for a change. For example,655// a change less than the required alignment is probably not worth656// attempting.657if (_avg_minor_pause->padded_average() > _avg_major_pause->padded_average()) {658adjust_eden_for_minor_pause_time(is_full_gc, desired_eden_size_ptr);659}660log_trace(gc, ergo)(661"PSAdaptiveSizePolicy::adjust_eden_for_pause_time "662"adjusting gen sizes for major pause (avg %f goal %f). "663"desired_eden_size " SIZE_FORMAT " eden delta " SIZE_FORMAT,664_avg_major_pause->average(), gc_pause_goal_sec(),665*desired_eden_size_ptr, eden_heap_delta);666}667668void PSAdaptiveSizePolicy::adjust_promo_for_throughput(bool is_full_gc,669size_t* desired_promo_size_ptr) {670671// Add some checks for a threshold for a change. For example,672// a change less than the required alignment is probably not worth673// attempting.674675if ((gc_cost() + mutator_cost()) == 0.0) {676return;677}678679log_trace(gc, ergo)("PSAdaptiveSizePolicy::adjust_promo_for_throughput(is_full: %d, promo: " SIZE_FORMAT "): mutator_cost %f major_gc_cost %f minor_gc_cost %f",680is_full_gc, *desired_promo_size_ptr, mutator_cost(), major_gc_cost(), minor_gc_cost());681682// Tenured generation683if (is_full_gc) {684// Calculate the change to use for the tenured gen.685size_t scaled_promo_heap_delta = 0;686// Can the increment to the generation be scaled?687if (gc_cost() >= 0.0 && major_gc_cost() >= 0.0) {688size_t promo_heap_delta =689promo_increment_with_supplement_aligned_up(*desired_promo_size_ptr);690double scale_by_ratio = major_gc_cost() / gc_cost();691scaled_promo_heap_delta =692(size_t) (scale_by_ratio * (double) promo_heap_delta);693log_trace(gc, ergo)("Scaled tenured increment: " SIZE_FORMAT " by %f down to " SIZE_FORMAT,694promo_heap_delta, scale_by_ratio, scaled_promo_heap_delta);695} else if (major_gc_cost() >= 0.0) {696// Scaling is not going to work. If the major gc time is the697// larger, give it a full increment.698if (major_gc_cost() >= minor_gc_cost()) {699scaled_promo_heap_delta =700promo_increment_with_supplement_aligned_up(*desired_promo_size_ptr);701}702} else {703// Don't expect to get here but it's ok if it does704// in the product build since the delta will be 0705// and nothing will change.706assert(false, "Unexpected value for gc costs");707}708709switch (AdaptiveSizeThroughPutPolicy) {710case 1:711// Early in the run the statistics might not be good. Until712// a specific number of collections have been, use the heuristic713// that a larger generation size means lower collection costs.714if (major_collection_estimator()->increment_will_decrease() ||715(_old_gen_change_for_major_throughput716<= AdaptiveSizePolicyInitializingSteps)) {717// Increase tenured generation size to reduce major collection cost718if ((*desired_promo_size_ptr + scaled_promo_heap_delta) >719*desired_promo_size_ptr) {720*desired_promo_size_ptr = _promo_size + scaled_promo_heap_delta;721}722set_change_old_gen_for_throughput(723increase_old_gen_for_throughput_true);724_old_gen_change_for_major_throughput++;725} else {726// EXPERIMENTAL ADJUSTMENT727// Record that decreasing the old gen size would decrease728// the major collection cost but don't do it.729// *desired_promo_size_ptr = _promo_size -730// promo_decrement_aligned_down(*desired_promo_size_ptr);731set_change_old_gen_for_throughput(732decrease_old_gen_for_throughput_true);733}734735break;736default:737// Simplest strategy738if ((*desired_promo_size_ptr + scaled_promo_heap_delta) >739*desired_promo_size_ptr) {740*desired_promo_size_ptr = *desired_promo_size_ptr +741scaled_promo_heap_delta;742}743set_change_old_gen_for_throughput(744increase_old_gen_for_throughput_true);745_old_gen_change_for_major_throughput++;746}747748log_trace(gc, ergo)("Adjusting tenured gen for throughput (avg %f goal %f). desired_promo_size " SIZE_FORMAT " promo_delta " SIZE_FORMAT ,749mutator_cost(),750_throughput_goal,751*desired_promo_size_ptr, scaled_promo_heap_delta);752}753}754755void PSAdaptiveSizePolicy::adjust_eden_for_throughput(bool is_full_gc,756size_t* desired_eden_size_ptr) {757758// Add some checks for a threshold for a change. For example,759// a change less than the required alignment is probably not worth760// attempting.761762if ((gc_cost() + mutator_cost()) == 0.0) {763return;764}765766log_trace(gc, ergo)("PSAdaptiveSizePolicy::adjust_eden_for_throughput(is_full: %d, cur_eden: " SIZE_FORMAT "): mutator_cost %f major_gc_cost %f minor_gc_cost %f",767is_full_gc, *desired_eden_size_ptr, mutator_cost(), major_gc_cost(), minor_gc_cost());768769// Young generation770size_t scaled_eden_heap_delta = 0;771// Can the increment to the generation be scaled?772if (gc_cost() >= 0.0 && minor_gc_cost() >= 0.0) {773size_t eden_heap_delta =774eden_increment_with_supplement_aligned_up(*desired_eden_size_ptr);775double scale_by_ratio = minor_gc_cost() / gc_cost();776assert(scale_by_ratio <= 1.0 && scale_by_ratio >= 0.0, "Scaling is wrong");777scaled_eden_heap_delta =778(size_t) (scale_by_ratio * (double) eden_heap_delta);779log_trace(gc, ergo)("Scaled eden increment: " SIZE_FORMAT " by %f down to " SIZE_FORMAT,780eden_heap_delta, scale_by_ratio, scaled_eden_heap_delta);781} else if (minor_gc_cost() >= 0.0) {782// Scaling is not going to work. If the minor gc time is the783// larger, give it a full increment.784if (minor_gc_cost() > major_gc_cost()) {785scaled_eden_heap_delta =786eden_increment_with_supplement_aligned_up(*desired_eden_size_ptr);787}788} else {789// Don't expect to get here but it's ok if it does790// in the product build since the delta will be 0791// and nothing will change.792assert(false, "Unexpected value for gc costs");793}794795// Use a heuristic for some number of collections to give796// the averages time to settle down.797switch (AdaptiveSizeThroughPutPolicy) {798case 1:799if (minor_collection_estimator()->increment_will_decrease() ||800(_young_gen_change_for_minor_throughput801<= AdaptiveSizePolicyInitializingSteps)) {802// Expand young generation size to reduce frequency of803// of collections.804if ((*desired_eden_size_ptr + scaled_eden_heap_delta) >805*desired_eden_size_ptr) {806*desired_eden_size_ptr =807*desired_eden_size_ptr + scaled_eden_heap_delta;808}809set_change_young_gen_for_throughput(810increase_young_gen_for_througput_true);811_young_gen_change_for_minor_throughput++;812} else {813// EXPERIMENTAL ADJUSTMENT814// Record that decreasing the young gen size would decrease815// the minor collection cost but don't do it.816// *desired_eden_size_ptr = _eden_size -817// eden_decrement_aligned_down(*desired_eden_size_ptr);818set_change_young_gen_for_throughput(819decrease_young_gen_for_througput_true);820}821break;822default:823if ((*desired_eden_size_ptr + scaled_eden_heap_delta) >824*desired_eden_size_ptr) {825*desired_eden_size_ptr =826*desired_eden_size_ptr + scaled_eden_heap_delta;827}828set_change_young_gen_for_throughput(829increase_young_gen_for_througput_true);830_young_gen_change_for_minor_throughput++;831}832833log_trace(gc, ergo)("Adjusting eden for throughput (avg %f goal %f). desired_eden_size " SIZE_FORMAT " eden delta " SIZE_FORMAT,834mutator_cost(), _throughput_goal, *desired_eden_size_ptr, scaled_eden_heap_delta);835}836837size_t PSAdaptiveSizePolicy::adjust_promo_for_footprint(838size_t desired_promo_size, size_t desired_sum) {839assert(desired_promo_size <= desired_sum, "Inconsistent parameters");840set_decrease_for_footprint(decrease_old_gen_for_footprint_true);841842size_t change = promo_decrement(desired_promo_size);843change = scale_down(change, desired_promo_size, desired_sum);844845size_t reduced_size = desired_promo_size - change;846847log_trace(gc, ergo)(848"AdaptiveSizePolicy::adjust_promo_for_footprint "849"adjusting tenured gen for footprint. "850"starting promo size " SIZE_FORMAT851" reduced promo size " SIZE_FORMAT852" promo delta " SIZE_FORMAT,853desired_promo_size, reduced_size, change );854855assert(reduced_size <= desired_promo_size, "Inconsistent result");856return reduced_size;857}858859size_t PSAdaptiveSizePolicy::adjust_eden_for_footprint(860size_t desired_eden_size, size_t desired_sum) {861assert(desired_eden_size <= desired_sum, "Inconsistent parameters");862set_decrease_for_footprint(decrease_young_gen_for_footprint_true);863864size_t change = eden_decrement(desired_eden_size);865change = scale_down(change, desired_eden_size, desired_sum);866867size_t reduced_size = desired_eden_size - change;868869log_trace(gc, ergo)(870"AdaptiveSizePolicy::adjust_eden_for_footprint "871"adjusting eden for footprint. "872" starting eden size " SIZE_FORMAT873" reduced eden size " SIZE_FORMAT874" eden delta " SIZE_FORMAT,875desired_eden_size, reduced_size, change);876877assert(reduced_size <= desired_eden_size, "Inconsistent result");878return reduced_size;879}880881// Scale down "change" by the factor882// part / total883// Don't align the results.884885size_t PSAdaptiveSizePolicy::scale_down(size_t change,886double part,887double total) {888assert(part <= total, "Inconsistent input");889size_t reduced_change = change;890if (total > 0) {891double fraction = part / total;892reduced_change = (size_t) (fraction * (double) change);893}894assert(reduced_change <= change, "Inconsistent result");895return reduced_change;896}897898size_t PSAdaptiveSizePolicy::eden_increment(size_t cur_eden,899uint percent_change) {900size_t eden_heap_delta;901eden_heap_delta = cur_eden / 100 * percent_change;902return eden_heap_delta;903}904905size_t PSAdaptiveSizePolicy::eden_increment(size_t cur_eden) {906return eden_increment(cur_eden, YoungGenerationSizeIncrement);907}908909size_t PSAdaptiveSizePolicy::eden_increment_with_supplement_aligned_up(910size_t cur_eden) {911size_t result = eden_increment(cur_eden,912YoungGenerationSizeIncrement + _young_gen_size_increment_supplement);913return align_up(result, _space_alignment);914}915916size_t PSAdaptiveSizePolicy::eden_decrement_aligned_down(size_t cur_eden) {917size_t eden_heap_delta = eden_decrement(cur_eden);918return align_down(eden_heap_delta, _space_alignment);919}920921size_t PSAdaptiveSizePolicy::eden_decrement(size_t cur_eden) {922size_t eden_heap_delta = eden_increment(cur_eden) /923AdaptiveSizeDecrementScaleFactor;924return eden_heap_delta;925}926927size_t PSAdaptiveSizePolicy::promo_increment(size_t cur_promo,928uint percent_change) {929size_t promo_heap_delta;930promo_heap_delta = cur_promo / 100 * percent_change;931return promo_heap_delta;932}933934size_t PSAdaptiveSizePolicy::promo_increment(size_t cur_promo) {935return promo_increment(cur_promo, TenuredGenerationSizeIncrement);936}937938size_t PSAdaptiveSizePolicy::promo_increment_with_supplement_aligned_up(939size_t cur_promo) {940size_t result = promo_increment(cur_promo,941TenuredGenerationSizeIncrement + _old_gen_size_increment_supplement);942return align_up(result, _space_alignment);943}944945size_t PSAdaptiveSizePolicy::promo_decrement_aligned_down(size_t cur_promo) {946size_t promo_heap_delta = promo_decrement(cur_promo);947return align_down(promo_heap_delta, _space_alignment);948}949950size_t PSAdaptiveSizePolicy::promo_decrement(size_t cur_promo) {951size_t promo_heap_delta = promo_increment(cur_promo);952promo_heap_delta = promo_heap_delta / AdaptiveSizeDecrementScaleFactor;953return promo_heap_delta;954}955956uint PSAdaptiveSizePolicy::compute_survivor_space_size_and_threshold(957bool is_survivor_overflow,958uint tenuring_threshold,959size_t survivor_limit) {960assert(survivor_limit >= _space_alignment,961"survivor_limit too small");962assert(is_aligned(survivor_limit, _space_alignment),963"survivor_limit not aligned");964965// This method is called even if the tenuring threshold and survivor966// spaces are not adjusted so that the averages are sampled above.967if (!UsePSAdaptiveSurvivorSizePolicy ||968!young_gen_policy_is_ready()) {969return tenuring_threshold;970}971972// We'll decide whether to increase or decrease the tenuring973// threshold based partly on the newly computed survivor size974// (if we hit the maximum limit allowed, we'll always choose to975// decrement the threshold).976bool incr_tenuring_threshold = false;977bool decr_tenuring_threshold = false;978979set_decrement_tenuring_threshold_for_gc_cost(false);980set_increment_tenuring_threshold_for_gc_cost(false);981set_decrement_tenuring_threshold_for_survivor_limit(false);982983if (!is_survivor_overflow) {984// Keep running averages on how much survived985986// We use the tenuring threshold to equalize the cost of major987// and minor collections.988// ThresholdTolerance is used to indicate how sensitive the989// tenuring threshold is to differences in cost between the990// collection types.991992// Get the times of interest. This involves a little work, so993// we cache the values here.994const double major_cost = major_gc_cost();995const double minor_cost = minor_gc_cost();996997if (minor_cost > major_cost * _threshold_tolerance_percent) {998// Minor times are getting too long; lower the threshold so999// less survives and more is promoted.1000decr_tenuring_threshold = true;1001set_decrement_tenuring_threshold_for_gc_cost(true);1002} else if (major_cost > minor_cost * _threshold_tolerance_percent) {1003// Major times are too long, so we want less promotion.1004incr_tenuring_threshold = true;1005set_increment_tenuring_threshold_for_gc_cost(true);1006}10071008} else {1009// Survivor space overflow occurred, so promoted and survived are1010// not accurate. We'll make our best guess by combining survived1011// and promoted and count them as survivors.1012//1013// We'll lower the tenuring threshold to see if we can correct1014// things. Also, set the survivor size conservatively. We're1015// trying to avoid many overflows from occurring if defnew size1016// is just too small.10171018decr_tenuring_threshold = true;1019}10201021// The padded average also maintains a deviation from the average;1022// we use this to see how good of an estimate we have of what survived.1023// We're trying to pad the survivor size as little as possible without1024// overflowing the survivor spaces.1025size_t target_size = align_up((size_t)_avg_survived->padded_average(),1026_space_alignment);1027target_size = MAX2(target_size, _space_alignment);10281029if (target_size > survivor_limit) {1030// Target size is bigger than we can handle. Let's also reduce1031// the tenuring threshold.1032target_size = survivor_limit;1033decr_tenuring_threshold = true;1034set_decrement_tenuring_threshold_for_survivor_limit(true);1035}10361037// Finally, increment or decrement the tenuring threshold, as decided above.1038// We test for decrementing first, as we might have hit the target size1039// limit.1040if (decr_tenuring_threshold && !(AlwaysTenure || NeverTenure)) {1041if (tenuring_threshold > 1) {1042tenuring_threshold--;1043}1044} else if (incr_tenuring_threshold && !(AlwaysTenure || NeverTenure)) {1045if (tenuring_threshold < MaxTenuringThreshold) {1046tenuring_threshold++;1047}1048}10491050// We keep a running average of the amount promoted which is used1051// to decide when we should collect the old generation (when1052// the amount of old gen free space is less than what we expect to1053// promote).10541055log_trace(gc, ergo)("avg_survived: %f avg_deviation: %f", _avg_survived->average(), _avg_survived->deviation());1056log_debug(gc, ergo)("avg_survived_padded_avg: %f", _avg_survived->padded_average());10571058log_trace(gc, ergo)("avg_promoted_avg: %f avg_promoted_dev: %f", avg_promoted()->average(), avg_promoted()->deviation());1059log_debug(gc, ergo)("avg_promoted_padded_avg: %f avg_pretenured_padded_avg: %f tenuring_thresh: %d target_size: " SIZE_FORMAT,1060avg_promoted()->padded_average(),1061_avg_pretenured->padded_average(),1062tenuring_threshold, target_size);10631064set_survivor_size(target_size);10651066return tenuring_threshold;1067}10681069void PSAdaptiveSizePolicy::update_averages(bool is_survivor_overflow,1070size_t survived,1071size_t promoted) {1072// Update averages1073if (!is_survivor_overflow) {1074// Keep running averages on how much survived1075_avg_survived->sample(survived);1076} else {1077size_t survived_guess = survived + promoted;1078_avg_survived->sample(survived_guess);1079}1080avg_promoted()->sample(promoted);10811082log_trace(gc, ergo)("AdaptiveSizePolicy::update_averages: survived: " SIZE_FORMAT " promoted: " SIZE_FORMAT " overflow: %s",1083survived, promoted, is_survivor_overflow ? "true" : "false");1084}10851086bool PSAdaptiveSizePolicy::print() const {10871088if (!UseAdaptiveSizePolicy) {1089return false;1090}10911092if (AdaptiveSizePolicy::print()) {1093AdaptiveSizePolicy::print_tenuring_threshold(PSScavenge::tenuring_threshold());1094return true;1095}10961097return false;1098}109911001101