< prev index next >

src/hotspot/share/gc/g1/g1Policy.cpp

Print this page
rev 59792 : imported patch 8244603-sjohanss-review

*** 60,69 **** --- 60,70 ---- _mmu_tracker(new G1MMUTrackerQueue(GCPauseIntervalMillis / 1000.0, MaxGCPauseMillis / 1000.0)), _ihop_control(create_ihop_control(&_predictor)), _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_max_length(0), _eden_surv_rate_group(new G1SurvRateGroup()), _survivor_surv_rate_group(new G1SurvRateGroup()), _reserve_factor((double) G1ReservePercent / 100.0),
*** 109,119 **** _young_gen_sizer->adjust_max_new_size(_g1h->max_expandable_regions()); _free_regions_at_end_of_collection = _g1h->num_free_regions(); ! update_young_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(); } --- 110,120 ---- _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(); // 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(); }
*** 198,241 **** desired_min_length = (uint) ceil(alloc_rate_ms * when_ms); } return desired_min_length; } ! uint G1Policy::update_young_max_and_target_length() { ! return update_young_max_and_target_length(_analytics->predict_rs_length()); } ! uint G1Policy::update_young_max_and_target_length(size_t rs_length) { ! uint unbounded_target_length = update_young_target_length(rs_length); ! update_max_gc_locker_expansion(); ! return unbounded_target_length; ! } ! ! uint G1Policy::update_young_target_length(size_t rs_length) { ! uint desired_length = calculate_young_desired_length(rs_length); ! _young_list_target_length = calculate_young_target_length(desired_length); ! ! log_debug(gc,ergo,heap)("Young target lengths: desired: %u target: %u", ! desired_length, _young_list_target_length); ! return desired_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. // 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(); assert(min_young_length_by_sizer >= 1, "invariant"); assert(max_young_length_by_sizer >= min_young_length_by_sizer, "invariant"); ! // Absolute minimum eden length. See above why. // 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; --- 199,244 ---- desired_min_length = (uint) ceil(alloc_rate_ms * when_ms); } return desired_min_length; } ! void G1Policy::update_young_length_bounds() { ! update_young_length_bounds(_analytics->predict_rs_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); } // 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(); assert(min_young_length_by_sizer >= 1, "invariant"); assert(max_young_length_by_sizer >= min_young_length_by_sizer, "invariant"); ! // 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;
*** 516,527 **** if (rs_length > _rs_length_prediction) { // 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_max_and_target_length(rs_length_prediction); } } void G1Policy::update_rs_length_prediction() { update_rs_length_prediction(_analytics->predict_rs_length()); --- 519,529 ---- if (rs_length > _rs_length_prediction) { // 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); } } void G1Policy::update_rs_length_prediction() { update_rs_length_prediction(_analytics->predict_rs_length());
*** 565,575 **** _eden_surv_rate_group->start_adding_regions(); // also call this on any additional surv rate groups _free_regions_at_end_of_collection = _g1h->num_free_regions(); _survivor_surv_rate_group->reset(); ! update_young_max_and_target_length(); update_rs_length_prediction(); _old_gen_alloc_tracker.reset_after_full_gc(); record_pause(FullGC, _full_collection_start_sec, end_sec); --- 567,577 ---- _eden_surv_rate_group->start_adding_regions(); // also call this on any additional surv rate groups _free_regions_at_end_of_collection = _g1h->num_free_regions(); _survivor_surv_rate_group->reset(); ! update_young_length_bounds(); update_rs_length_prediction(); _old_gen_alloc_tracker.reset_after_full_gc(); record_pause(FullGC, _full_collection_start_sec, end_sec);
*** 895,914 **** update_rs_length_prediction(); // 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) { ! // 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_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()); } else { // Any garbage collection triggered as periodic collection resets the time-to-mixed --- 897,911 ---- update_rs_length_prediction(); // 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(); _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(), this_pause_was_young_only); _ihop_control->send_trace_event(_g1h->gc_tracer_stw()); } else { // Any garbage collection triggered as periodic collection resets the time-to-mixed
*** 954,964 **** } } 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. // Avoid using really small application times that might create samples with --- 951,960 ----
*** 982,991 **** --- 978,992 ---- // As an approximation for the young gc promotion rates during marking we use // all of them. In many applications there are only a few if any young gcs during // 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. + uint 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; } if (report) {
*** 1088,1110 **** void G1Policy::print_age_table() { _survivors_age_table.print_age_table(_tenuring_threshold); } ! void G1Policy::update_max_gc_locker_expansion() { uint expansion_region_num = 0; if (GCLockerEdenExpansionPercent > 0) { double perc = (double) GCLockerEdenExpansionPercent / 100.0; double expansion_region_num_d = perc * (double) _young_list_target_length; // We use ceiling so that if expansion_region_num_d is > 0.0 (but // less than 1.0) we'll get 1. expansion_region_num = (uint) ceil(expansion_region_num_d); } else { assert(expansion_region_num == 0, "sanity"); } ! _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. void G1Policy::update_survivors_policy() { double max_survivor_regions_d = --- 1089,1112 ---- void G1Policy::print_age_table() { _survivors_age_table.print_age_table(_tenuring_threshold); } ! uint G1Policy::calculate_young_max_length(uint target_young_length) const { uint expansion_region_num = 0; if (GCLockerEdenExpansionPercent > 0) { double perc = (double) GCLockerEdenExpansionPercent / 100.0; double expansion_region_num_d = perc * (double) _young_list_target_length; // We use ceiling so that if expansion_region_num_d is > 0.0 (but // less than 1.0) we'll get 1. expansion_region_num = (uint) ceil(expansion_region_num_d); } 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; } // Calculates survivor space parameters. void G1Policy::update_survivors_policy() { double max_survivor_regions_d =
< prev index next >