8248650: [BACKOUT] Backout JDK-8244603 because it generates too much noise in CI

Reviewed-by: kbarrett
This commit is contained in:
Thomas Schatzl 2020-07-02 09:40:27 +02:00
parent 51937e18f8
commit dc63bf261b
3 changed files with 190 additions and 305 deletions

View File

@ -224,11 +224,7 @@ void G1Analytics::report_rs_length(double rs_length) {
}
double G1Analytics::predict_alloc_rate_ms() const {
if (enough_samples_available(_alloc_rate_ms_seq)) {
return predict_zero_bounded(_alloc_rate_ms_seq);
} else {
return 0.0;
}
return predict_zero_bounded(_alloc_rate_ms_seq);
}
double G1Analytics::predict_concurrent_refine_rate_ms() const {

View File

@ -46,7 +46,6 @@
#include "gc/shared/gcPolicyCounters.hpp"
#include "logging/log.hpp"
#include "runtime/arguments.hpp"
#include "runtime/globals.hpp"
#include "runtime/java.hpp"
#include "runtime/mutexLocker.hpp"
#include "utilities/debug.hpp"
@ -62,8 +61,8 @@ G1Policy::G1Policy(STWGCTimer* gc_timer) :
_policy_counters(new GCPolicyCounters("GarbageFirst", 1, 2)),
_full_collection_start_sec(0.0),
_collection_pause_end_millis(os::javaTimeNanos() / NANOSECS_PER_MILLISEC),
_young_list_desired_length(0),
_young_list_target_length(0),
_young_list_fixed_length(0),
_young_list_max_length(0),
_eden_surv_rate_group(new G1SurvRateGroup()),
_survivor_surv_rate_group(new G1SurvRateGroup()),
@ -108,11 +107,14 @@ void G1Policy::init(G1CollectedHeap* g1h, G1CollectionSet* collection_set) {
assert(Heap_lock->owned_by_self(), "Locking discipline.");
if (!use_adaptive_young_list_length()) {
_young_list_fixed_length = _young_gen_sizer->min_desired_young_length();
}
_young_gen_sizer->adjust_max_new_size(_g1h->max_expandable_regions());
_free_regions_at_end_of_collection = _g1h->num_free_regions();
update_young_length_bounds();
update_young_list_max_and_target_length();
// We may immediately start allocating regions and placing them on the
// collection set list. Initialize the per-collection set info
_collection_set->start_incremental_building();
@ -187,254 +189,158 @@ void G1Policy::record_new_heap_size(uint new_number_of_regions) {
_ihop_control->update_target_occupancy(new_number_of_regions * HeapRegion::GrainBytes);
}
uint G1Policy::calculate_desired_eden_length_by_mmu() const {
// One could argue that any useful eden length to keep any MMU would be 1, but
// in theory this is possible. Other constraints enforce a minimum eden of 1
// anyway.
uint G1Policy::calculate_young_list_desired_min_length(uint base_min_length) const {
uint desired_min_length = 0;
if (use_adaptive_young_list_length()) {
double now_sec = os::elapsedTime();
double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0;
double alloc_rate_ms = _analytics->predict_alloc_rate_ms();
desired_min_length = (uint) ceil(alloc_rate_ms * when_ms);
if (_analytics->num_alloc_rate_ms() > 3) {
double now_sec = os::elapsedTime();
double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0;
double alloc_rate_ms = _analytics->predict_alloc_rate_ms();
desired_min_length = (uint) ceil(alloc_rate_ms * when_ms);
} else {
// otherwise we don't have enough info to make the prediction
}
}
return desired_min_length;
desired_min_length += base_min_length;
// make sure we don't go below any user-defined minimum bound
return MAX2(_young_gen_sizer->min_desired_young_length(), desired_min_length);
}
void G1Policy::update_young_length_bounds() {
update_young_length_bounds(_analytics->predict_rs_length());
uint G1Policy::calculate_young_list_desired_max_length() const {
// Here, we might want to also take into account any additional
// constraints (i.e., user-defined minimum bound). Currently, we
// effectively don't set this bound.
return _young_gen_sizer->max_desired_young_length();
}
void G1Policy::update_young_length_bounds(size_t rs_length) {
_young_list_desired_length = calculate_young_desired_length(rs_length);
_young_list_target_length = calculate_young_target_length(_young_list_desired_length);
_young_list_max_length = calculate_young_max_length(_young_list_target_length);
log_debug(gc,ergo,heap)("Young list lengths: desired: %u, target: %u, max: %u",
_young_list_desired_length,
_young_list_target_length,
_young_list_max_length);
uint G1Policy::update_young_list_max_and_target_length() {
return update_young_list_max_and_target_length(_analytics->predict_rs_length());
}
// Calculates desired young gen length. It is calculated from:
//
// - sizer min/max bounds on young gen
// - pause time goal for whole young gen evacuation
// - MMU goal influencing eden to make GCs spaced apart.
// - a minimum one eden region length.
//
// We may enter with already allocated eden and survivor regions, that may be
// higher than the maximum, or the above goals may result in a desired value
// smaller than are already allocated.
// The main reason is revising young length, with our without the GCLocker being
// active.
//
uint G1Policy::calculate_young_desired_length(size_t rs_length) const {
uint min_young_length_by_sizer = _young_gen_sizer->min_desired_young_length();
uint max_young_length_by_sizer = _young_gen_sizer->max_desired_young_length();
uint G1Policy::update_young_list_max_and_target_length(size_t rs_length) {
uint unbounded_target_length = update_young_list_target_length(rs_length);
update_max_gc_locker_expansion();
return unbounded_target_length;
}
assert(min_young_length_by_sizer >= 1, "invariant");
assert(max_young_length_by_sizer >= min_young_length_by_sizer, "invariant");
uint G1Policy::update_young_list_target_length(size_t rs_length) {
YoungTargetLengths young_lengths = young_list_target_lengths(rs_length);
_young_list_target_length = young_lengths.first;
// Absolute minimum eden length.
// Enforcing a minimum eden length helps at startup when the predictors are not
// yet trained on the application to avoid unnecessary (but very short) full gcs
// on very small (initial) heaps.
uint const MinDesiredEdenLength = 1;
return young_lengths.second;
}
G1Policy::YoungTargetLengths G1Policy::young_list_target_lengths(size_t rs_length) const {
YoungTargetLengths result;
// Calculate the absolute and desired min bounds first.
// This is how many survivor regions we already have.
const uint survivor_length = _g1h->survivor_regions_count();
// Size of the already allocated young gen.
const uint allocated_young_length = _g1h->young_regions_count();
// This is the absolute minimum young length that we can return. Ensure that we
// don't go below any user-defined minimum bound; but we might have already
// allocated more than that for reasons. In this case, use that.
uint absolute_min_young_length = MAX2(allocated_young_length, min_young_length_by_sizer);
// Calculate the absolute max bounds. After evac failure or when revising the
// young length we might have exceeded absolute min length or absolute_max_length,
// so adjust the result accordingly.
uint absolute_max_young_length = MAX2(max_young_length_by_sizer, absolute_min_young_length);
// This is how many young regions we already have (currently: the survivors).
const uint base_min_length = _g1h->survivor_regions_count();
uint desired_min_length = calculate_young_list_desired_min_length(base_min_length);
// This is the absolute minimum young length. Ensure that we
// will at least have one eden region available for allocation.
uint absolute_min_length = base_min_length + MAX2(_g1h->eden_regions_count(), (uint)1);
// If we shrank the young list target it should not shrink below the current size.
desired_min_length = MAX2(desired_min_length, absolute_min_length);
// Calculate the absolute and desired max bounds.
uint desired_eden_length_by_mmu = 0;
uint desired_eden_length_by_pause = 0;
uint desired_eden_length_before_mixed = 0;
uint desired_max_length = calculate_young_list_desired_max_length();
uint desired_young_length = 0;
uint young_list_target_length = 0;
if (use_adaptive_young_list_length()) {
desired_eden_length_by_mmu = calculate_desired_eden_length_by_mmu();
const size_t pending_cards = _analytics->predict_pending_cards();
double survivor_base_time_ms = predict_base_elapsed_time_ms(pending_cards, rs_length);
if (!next_gc_should_be_mixed(NULL, NULL)) {
desired_eden_length_by_pause =
calculate_desired_eden_length_by_pause(survivor_base_time_ms,
absolute_min_young_length - survivor_length,
absolute_max_young_length - survivor_length);
if (collector_state()->in_young_only_phase()) {
young_list_target_length =
calculate_young_list_target_length(rs_length,
base_min_length,
desired_min_length,
desired_max_length);
} else {
desired_eden_length_before_mixed =
calculate_desired_eden_length_before_mixed(survivor_base_time_ms,
absolute_min_young_length - survivor_length,
absolute_max_young_length - survivor_length);
// Don't calculate anything and let the code below bound it to
// the desired_min_length, i.e., do the next GC as soon as
// possible to maximize how many old regions we can add to it.
}
// Above either sets desired_eden_length_by_pause or desired_eden_length_before_mixed,
// the other is zero. Use the one that has been set below.
uint desired_eden_length = MAX2(desired_eden_length_by_pause,
desired_eden_length_before_mixed);
// Finally incorporate MMU concerns; assume that it overrides the pause time
// goal, as the default value has been chosen to effectively disable it.
// Also request at least one eden region, see above for reasons.
desired_eden_length = MAX3(desired_eden_length,
desired_eden_length_by_mmu,
MinDesiredEdenLength);
desired_young_length = desired_eden_length + survivor_length;
} else {
// The user asked for a fixed young gen so we'll fix the young gen
// whether the next GC is young or mixed.
desired_young_length = min_young_length_by_sizer;
}
// Clamp to absolute min/max after we determined desired lengths.
desired_young_length = clamp(desired_young_length, absolute_min_young_length, absolute_max_young_length);
log_trace(gc, ergo, heap)("Young desired length %u "
"survivor length %u "
"allocated young length %u "
"absolute min young length %u "
"absolute max young length %u "
"desired eden length by mmu %u "
"desired eden length by pause %u "
"desired eden length before mixed %u"
"desired eden length by default %u",
desired_young_length, survivor_length,
allocated_young_length, absolute_min_young_length,
absolute_max_young_length, desired_eden_length_by_mmu,
desired_eden_length_by_pause,
desired_eden_length_before_mixed,
MinDesiredEdenLength);
assert(desired_young_length >= allocated_young_length, "must be");
return desired_young_length;
}
// Limit the desired (wished) young length by current free regions. If the request
// can be satisfied without using up reserve regions, do so, otherwise eat into
// the reserve, giving away at most what the heap sizer allows.
uint G1Policy::calculate_young_target_length(uint desired_young_length) const {
uint allocated_young_length = _g1h->young_regions_count();
uint receiving_additional_eden;
if (allocated_young_length >= desired_young_length) {
// Already used up all we actually want (may happen as G1 revises the
// young list length concurrently, or caused by gclocker). Do not allow more,
// potentially resulting in GC.
receiving_additional_eden = 0;
log_trace(gc, ergo, heap)("Young target length: Already used up desired young %u allocated %u",
desired_young_length,
allocated_young_length);
} else {
// Now look at how many free regions are there currently, and the heap reserve.
// We will try our best not to "eat" into the reserve as long as we can. If we
// do, we at most eat the sizer's minimum regions into the reserve or half the
// reserve rounded up (if possible; this is an arbitrary value).
uint max_to_eat_into_reserve = MIN2(_young_gen_sizer->min_desired_young_length(),
(_reserve_regions + 1) / 2);
log_trace(gc, ergo, heap)("Young target length: Common "
"free regions at end of collection %u "
"desired young length %u "
"reserve region %u "
"max to eat into reserve %u",
_free_regions_at_end_of_collection,
desired_young_length,
_reserve_regions,
max_to_eat_into_reserve);
if (_free_regions_at_end_of_collection <= _reserve_regions) {
// Fully eat (or already eating) into the reserve, hand back at most absolute_min_length regions.
uint receiving_young = MIN3(_free_regions_at_end_of_collection,
desired_young_length,
max_to_eat_into_reserve);
// We could already have allocated more regions than what we could get
// above.
receiving_additional_eden = allocated_young_length < receiving_young ?
receiving_young - allocated_young_length : 0;
log_trace(gc, ergo, heap)("Young target length: Fully eat into reserve "
"receiving young %u receiving additional eden %u",
receiving_young,
receiving_additional_eden);
} else if (_free_regions_at_end_of_collection < (desired_young_length + _reserve_regions)) {
// Partially eat into the reserve, at most max_to_eat_into_reserve regions.
uint free_outside_reserve = _free_regions_at_end_of_collection - _reserve_regions;
assert(free_outside_reserve < desired_young_length,
"must be %u %u",
free_outside_reserve, desired_young_length);
uint receiving_within_reserve = MIN2(desired_young_length - free_outside_reserve,
max_to_eat_into_reserve);
uint receiving_young = free_outside_reserve + receiving_within_reserve;
// Again, we could have already allocated more than we could get.
receiving_additional_eden = allocated_young_length < receiving_young ?
receiving_young - allocated_young_length : 0;
log_trace(gc, ergo, heap)("Young target length: Partially eat into reserve "
"free outside reserve %u "
"receiving within reserve %u "
"receiving young %u "
"receiving additional eden %u",
free_outside_reserve, receiving_within_reserve,
receiving_young, receiving_additional_eden);
} else {
// No need to use the reserve.
receiving_additional_eden = desired_young_length - allocated_young_length;
log_trace(gc, ergo, heap)("Young target length: No need to use reserve "
"receiving additional eden %u",
receiving_additional_eden);
}
young_list_target_length = _young_list_fixed_length;
}
uint target_young_length = allocated_young_length + receiving_additional_eden;
result.second = young_list_target_length;
assert(target_young_length >= allocated_young_length, "must be");
// We will try our best not to "eat" into the reserve.
uint absolute_max_length = 0;
if (_free_regions_at_end_of_collection > _reserve_regions) {
absolute_max_length = _free_regions_at_end_of_collection - _reserve_regions;
}
if (desired_max_length > absolute_max_length) {
desired_max_length = absolute_max_length;
}
log_trace(gc, ergo, heap)("Young target length: "
"young target length %u "
"allocated young length %u "
"received additional eden %u",
target_young_length, allocated_young_length,
receiving_additional_eden);
return target_young_length;
// Make sure we don't go over the desired max length, nor under the
// desired min length. In case they clash, desired_min_length wins
// which is why that test is second.
if (young_list_target_length > desired_max_length) {
young_list_target_length = desired_max_length;
}
if (young_list_target_length < desired_min_length) {
young_list_target_length = desired_min_length;
}
assert(young_list_target_length > base_min_length,
"we should be able to allocate at least one eden region");
assert(young_list_target_length >= absolute_min_length, "post-condition");
result.first = young_list_target_length;
return result;
}
uint G1Policy::calculate_desired_eden_length_by_pause(double base_time_ms,
uint min_eden_length,
uint max_eden_length) const {
uint G1Policy::calculate_young_list_target_length(size_t rs_length,
uint base_min_length,
uint desired_min_length,
uint desired_max_length) const {
assert(use_adaptive_young_list_length(), "pre-condition");
assert(collector_state()->in_young_only_phase(), "only call this for young GCs");
assert(min_eden_length <= max_eden_length, "must be %u %u", min_eden_length, max_eden_length);
// In case some edge-condition makes the desired max length too small...
if (desired_max_length <= desired_min_length) {
return desired_min_length;
}
// We'll adjust min_young_length and max_young_length not to include
// the already allocated young regions (i.e., so they reflect the
// min and max eden regions we'll allocate). The base_min_length
// will be reflected in the predictions by the
// survivor_regions_evac_time prediction.
assert(desired_min_length > base_min_length, "invariant");
uint min_young_length = desired_min_length - base_min_length;
assert(desired_max_length > base_min_length, "invariant");
uint max_young_length = desired_max_length - base_min_length;
const double target_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0;
const size_t pending_cards = _analytics->predict_pending_cards();
const double base_time_ms = predict_base_elapsed_time_ms(pending_cards, rs_length);
const uint available_free_regions = _free_regions_at_end_of_collection;
const uint base_free_regions =
available_free_regions > _reserve_regions ? available_free_regions - _reserve_regions : 0;
// Here, we will make sure that the shortest young length that
// makes sense fits within the target pause time.
G1YoungLengthPredictor p(base_time_ms,
_free_regions_at_end_of_collection,
_mmu_tracker->max_gc_time() * 1000.0,
base_free_regions,
target_pause_time_ms,
this);
if (p.will_fit(min_eden_length)) {
if (p.will_fit(min_young_length)) {
// The shortest young length will fit into the target pause time;
// we'll now check whether the absolute maximum number of young
// regions will fit in the target pause time. If not, we'll do
// a binary search between min_young_length and max_young_length.
if (p.will_fit(max_eden_length)) {
if (p.will_fit(max_young_length)) {
// The maximum young length will fit into the target pause time.
// We are done so set min young length to the maximum length (as
// the result is assumed to be returned in min_young_length).
min_eden_length = max_eden_length;
min_young_length = max_young_length;
} else {
// The maximum possible number of young regions will not fit within
// the target pause time so we'll search for the optimal
@ -451,56 +357,37 @@ uint G1Policy::calculate_desired_eden_length_by_pause(double base_time_ms,
// does, it becomes the new min. If it doesn't, it becomes
// the new max. This way we maintain the loop invariants.
assert(min_eden_length < max_eden_length, "invariant");
uint diff = (max_eden_length - min_eden_length) / 2;
assert(min_young_length < max_young_length, "invariant");
uint diff = (max_young_length - min_young_length) / 2;
while (diff > 0) {
uint eden_length = min_eden_length + diff;
if (p.will_fit(eden_length)) {
min_eden_length = eden_length;
uint young_length = min_young_length + diff;
if (p.will_fit(young_length)) {
min_young_length = young_length;
} else {
max_eden_length = eden_length;
max_young_length = young_length;
}
assert(min_eden_length < max_eden_length, "invariant");
diff = (max_eden_length - min_eden_length) / 2;
assert(min_young_length < max_young_length, "invariant");
diff = (max_young_length - min_young_length) / 2;
}
// The results is min_young_length which, according to the
// loop invariants, should fit within the target pause time.
// These are the post-conditions of the binary search above:
assert(min_eden_length < max_eden_length,
"otherwise we should have discovered that max_eden_length "
assert(min_young_length < max_young_length,
"otherwise we should have discovered that max_young_length "
"fits into the pause target and not done the binary search");
assert(p.will_fit(min_eden_length),
"min_eden_length, the result of the binary search, should "
assert(p.will_fit(min_young_length),
"min_young_length, the result of the binary search, should "
"fit into the pause target");
assert(!p.will_fit(min_eden_length + 1),
"min_eden_length, the result of the binary search, should be "
assert(!p.will_fit(min_young_length + 1),
"min_young_length, the result of the binary search, should be "
"optimal, so no larger length should fit into the pause target");
}
} else {
// Even the minimum length doesn't fit into the pause time
// target, return it as the result nevertheless.
}
return min_eden_length;
}
uint G1Policy::calculate_desired_eden_length_before_mixed(double survivor_base_time_ms,
uint min_eden_length,
uint max_eden_length) const {
G1CollectionSetCandidates* candidates = _collection_set->candidates();
uint min_old_regions_end = MIN2(candidates->cur_idx() + calc_min_old_cset_length(), candidates->num_regions());
double predicted_region_evac_time_ms = survivor_base_time_ms;
for (uint i = candidates->cur_idx(); i < min_old_regions_end; i++) {
HeapRegion* r = candidates->at(i);
predicted_region_evac_time_ms += predict_region_total_time_ms(r, false);
}
uint desired_eden_length_by_min_cset_length =
calculate_desired_eden_length_by_pause(predicted_region_evac_time_ms,
min_eden_length,
max_eden_length);
return desired_eden_length_by_min_cset_length;
return base_min_length + min_young_length;
}
double G1Policy::predict_survivor_regions_evac_time() const {
@ -521,7 +408,8 @@ void G1Policy::revise_young_list_target_length_if_necessary(size_t rs_length) {
// add 10% to avoid having to recalculate often
size_t rs_length_prediction = rs_length * 1100 / 1000;
update_rs_length_prediction(rs_length_prediction);
update_young_length_bounds(rs_length_prediction);
update_young_list_max_and_target_length(rs_length_prediction);
}
}
@ -569,7 +457,7 @@ void G1Policy::record_full_collection_end() {
_free_regions_at_end_of_collection = _g1h->num_free_regions();
_survivor_surv_rate_group->reset();
update_young_length_bounds();
update_young_list_max_and_target_length();
update_rs_length_prediction();
_old_gen_alloc_tracker.reset_after_full_gc();
@ -899,11 +787,16 @@ void G1Policy::record_collection_pause_end(double pause_time_ms) {
// Do not update dynamic IHOP due to G1 periodic collection as it is highly likely
// that in this case we are not running in a "normal" operating mode.
if (_g1h->gc_cause() != GCCause::_g1_periodic_collection) {
update_young_length_bounds();
// IHOP control wants to know the expected young gen length if it were not
// restrained by the heap reserve. Using the actual length would make the
// prediction too small and the limit the young gen every time we get to the
// predicted target occupancy.
size_t last_unrestrained_young_length = update_young_list_max_and_target_length();
_old_gen_alloc_tracker.reset_after_young_gc(app_time_ms / 1000.0);
update_ihop_prediction(_old_gen_alloc_tracker.last_cycle_duration(),
_old_gen_alloc_tracker.last_cycle_old_bytes(),
last_unrestrained_young_length * HeapRegion::GrainBytes,
this_pause_was_young_only);
_ihop_control->send_trace_event(_g1h->gc_tracer_stw());
@ -953,6 +846,7 @@ G1IHOPControl* G1Policy::create_ihop_control(const G1Predictions* predictor){
void G1Policy::update_ihop_prediction(double mutator_time_s,
size_t mutator_alloc_bytes,
size_t young_gen_size,
bool this_gc_was_young_only) {
// Always try to update IHOP prediction. Even evacuation failures give information
// about e.g. whether to start IHOP earlier next time.
@ -980,11 +874,6 @@ void G1Policy::update_ihop_prediction(double mutator_time_s,
// marking, which makes any prediction useless. This increases the accuracy of the
// prediction.
if (this_gc_was_young_only && mutator_time_s > min_valid_time) {
// IHOP control wants to know the expected young gen length if it were not
// restrained by the heap reserve. Using the actual length would make the
// prediction too small and the limit the young gen every time we get to the
// predicted target occupancy.
size_t young_gen_size = young_list_desired_length() * HeapRegion::GrainBytes;
_ihop_control->update_allocation_info(mutator_time_s, mutator_alloc_bytes, young_gen_size);
report = true;
}
@ -1091,7 +980,7 @@ void G1Policy::print_age_table() {
_survivors_age_table.print_age_table(_tenuring_threshold);
}
uint G1Policy::calculate_young_max_length(uint target_young_length) const {
void G1Policy::update_max_gc_locker_expansion() {
uint expansion_region_num = 0;
if (GCLockerEdenExpansionPercent > 0) {
double perc = (double) GCLockerEdenExpansionPercent / 100.0;
@ -1102,9 +991,8 @@ uint G1Policy::calculate_young_max_length(uint target_young_length) const {
} else {
assert(expansion_region_num == 0, "sanity");
}
uint max_length = target_young_length + expansion_region_num;
assert(target_young_length <= max_length, "post-condition");
return max_length;
_young_list_max_length = _young_list_target_length + expansion_region_num;
assert(_young_list_target_length <= _young_list_max_length, "post-condition");
}
// Calculates survivor space parameters.
@ -1313,10 +1201,8 @@ bool G1Policy::next_gc_should_be_mixed(const char* true_action_str,
const char* false_action_str) const {
G1CollectionSetCandidates* candidates = _collection_set->candidates();
if (candidates == NULL || candidates->is_empty()) {
if (false_action_str != NULL) {
log_debug(gc, ergo)("%s (candidate old regions not available)", false_action_str);
}
if (candidates->is_empty()) {
log_debug(gc, ergo)("%s (candidate old regions not available)", false_action_str);
return false;
}
@ -1325,16 +1211,12 @@ bool G1Policy::next_gc_should_be_mixed(const char* true_action_str,
double reclaimable_percent = reclaimable_bytes_percent(reclaimable_bytes);
double threshold = (double) G1HeapWastePercent;
if (reclaimable_percent <= threshold) {
if (false_action_str != NULL) {
log_debug(gc, ergo)("%s (reclaimable percentage not over threshold). candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) threshold: " UINTX_FORMAT,
false_action_str, candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, G1HeapWastePercent);
}
log_debug(gc, ergo)("%s (reclaimable percentage not over threshold). candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) threshold: " UINTX_FORMAT,
false_action_str, candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, G1HeapWastePercent);
return false;
}
if (true_action_str != NULL) {
log_debug(gc, ergo)("%s (candidate old regions available). candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) threshold: " UINTX_FORMAT,
true_action_str, candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, G1HeapWastePercent);
}
log_debug(gc, ergo)("%s (candidate old regions available). candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) threshold: " UINTX_FORMAT,
true_action_str, candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, G1HeapWastePercent);
return true;
}

View File

@ -60,6 +60,7 @@ class G1Policy: public CHeapObj<mtGC> {
// Update the IHOP control with necessary statistics.
void update_ihop_prediction(double mutator_time_s,
size_t mutator_alloc_bytes,
size_t young_gen_size,
bool this_gc_was_young_only);
void report_ihop_statistics();
@ -75,8 +76,8 @@ class G1Policy: public CHeapObj<mtGC> {
jlong _collection_pause_end_millis;
uint _young_list_desired_length;
uint _young_list_target_length;
uint _young_list_fixed_length;
// The max number of regions we can extend the eden by while the GC
// locker is active. This should be >= _young_list_target_length;
@ -169,10 +170,6 @@ public:
private:
G1CollectionSet* _collection_set;
bool next_gc_should_be_mixed(const char* true_action_str,
const char* false_action_str) const;
double average_time_ms(G1GCPhaseTimes::GCParPhases phase) const;
double other_time_ms(double pause_time_ms) const;
@ -192,38 +189,44 @@ private:
double _mark_remark_start_sec;
double _mark_cleanup_start_sec;
// Updates the internal young gen maximum and target and desired lengths.
// If no rs_length parameter is passed, predict the RS length using the
// prediction model, otherwise use the given rs_length as the prediction.
void update_young_length_bounds();
void update_young_length_bounds(size_t rs_length);
// Updates the internal young list maximum and target lengths. Returns the
// unbounded young list target length. If no rs_length parameter is passed,
// predict the RS length using the prediction model, otherwise use the
// given rs_length as the prediction.
uint update_young_list_max_and_target_length();
uint update_young_list_max_and_target_length(size_t rs_length);
// Calculate and return the minimum desired eden length based on the MMU target.
uint calculate_desired_eden_length_by_mmu() const;
// Update the young list target length either by setting it to the
// desired fixed value or by calculating it using G1's pause
// prediction model.
// Returns the unbounded young list target length.
uint update_young_list_target_length(size_t rs_length);
// Calculate and return the desired eden length that can fit into the pause time goal.
// The parameters are: rs_length represents the prediction of how large the
// young RSet lengths will be, min_eden_length and max_eden_length are the bounds
// (inclusive) within eden can grow.
uint calculate_desired_eden_length_by_pause(double base_time_ms,
uint min_eden_length,
uint max_eden_length) const;
// Calculate and return the minimum desired young list target
// length. This is the minimum desired young list length according
// to the user's inputs.
uint calculate_young_list_desired_min_length(uint base_min_length) const;
// Calculates the desired eden length before mixed gc so that after adding the
// minimum amount of old gen regions from the collection set, the eden fits into
// the pause time goal.
uint calculate_desired_eden_length_before_mixed(double survivor_base_time_ms,
uint min_eden_length,
uint max_eden_length) const;
// Calculate and return the maximum desired young list target
// length. This is the maximum desired young list length according
// to the user's inputs.
uint calculate_young_list_desired_max_length() const;
// Calculate desired young length based on current situation without taking actually
// available free regions into account.
uint calculate_young_desired_length(size_t rs_length) const;
// Limit the given desired young length to available free regions.
uint calculate_young_target_length(uint desired_young_length) const;
// The GCLocker might cause us to need more regions than the target. Calculate
// the maximum number of regions to use in that case.
uint calculate_young_max_length(uint target_young_length) const;
// Calculate and return the maximum young list target length that
// can fit into the pause time goal. The parameters are: rs_length
// represent the prediction of how large the young RSet lengths will
// be, base_min_length is the already existing number of regions in
// the young list, min_length and max_length are the desired min and
// max young list length according to the user's inputs.
uint calculate_young_list_target_length(size_t rs_length,
uint base_min_length,
uint desired_min_length,
uint desired_max_length) const;
// Result of the bounded_young_list_target_length() method, containing both the
// bounded as well as the unbounded young list target lengths in this order.
typedef Pair<uint, uint, StackObj> YoungTargetLengths;
YoungTargetLengths young_list_target_lengths(size_t rs_length) const;
void update_rs_length_prediction();
void update_rs_length_prediction(size_t prediction);
@ -332,6 +335,9 @@ public:
void print_phases();
bool next_gc_should_be_mixed(const char* true_action_str,
const char* false_action_str) const;
// Calculate and return the number of initial and optional old gen regions from
// the given collection set candidates and the remaining time.
void calculate_old_collection_set_regions(G1CollectionSetCandidates* candidates,
@ -368,7 +374,6 @@ public:
// the initial-mark work and start a marking cycle.
void decide_on_conc_mark_initiation();
uint young_list_desired_length() const { return _young_list_desired_length; }
size_t young_list_target_length() const { return _young_list_target_length; }
bool should_allocate_mutator_region() const;
@ -429,6 +434,8 @@ public:
void print_age_table();
void update_max_gc_locker_expansion();
void update_survivors_policy();
virtual bool force_upgrade_to_full() {