src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp

Print this page
rev 2907 : 7113021: G1: automatically enable young gen size auto-tuning when -Xms==-Xmx
Summary: Use a percentage of -Xms as min and another percentage of -Xmx as max for the young gen size
Reviewed-by: tonyp

*** 134,144 **** _recent_gc_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), _all_pause_times_ms(new NumberSeq()), _stop_world_start(0.0), _all_stop_world_times_ms(new NumberSeq()), _all_yield_times_ms(new NumberSeq()), - _using_new_ratio_calculations(false), _summary(new Summary()), _cur_clear_ct_time_ms(0.0), _mark_closure_time_ms(0.0), --- 134,143 ----
*** 405,419 **** // for the first time during initialization. _reserve_regions = 0; initialize_all(); _collectionSetChooser = new CollectionSetChooser(); ! } ! ! // Increment "i", mod "len" ! static void inc_mod(int& i, int len) { ! i++; if (i == len) i = 0; } void G1CollectorPolicy::initialize_flags() { set_min_alignment(HeapRegion::GrainBytes); set_max_alignment(GenRemSet::max_alignment_constraint(rem_set_name())); --- 404,414 ---- // for the first time during initialization. _reserve_regions = 0; initialize_all(); _collectionSetChooser = new CollectionSetChooser(); ! _young_gen_sizer = new G1YoungGenSizer(); // Must be after call to initialize_flags } void G1CollectorPolicy::initialize_flags() { set_min_alignment(HeapRegion::GrainBytes); set_max_alignment(GenRemSet::max_alignment_constraint(rem_set_name()));
*** 421,495 **** vm_exit_during_initialization("Invalid survivor ratio specified"); } CollectorPolicy::initialize_flags(); } ! // The easiest way to deal with the parsing of the NewSize / ! // MaxNewSize / etc. parameteres is to re-use the code in the ! // TwoGenerationCollectorPolicy class. This is similar to what ! // ParallelScavenge does with its GenerationSizer class (see ! // ParallelScavengeHeap::initialize()). We might change this in the ! // future, but it's a good start. ! class G1YoungGenSizer : public TwoGenerationCollectorPolicy { ! private: ! size_t size_to_region_num(size_t byte_size) { ! return MAX2((size_t) 1, byte_size / HeapRegion::GrainBytes); ! } ! ! public: ! G1YoungGenSizer() { ! initialize_flags(); ! initialize_size_info(); ! } ! size_t min_young_region_num() { ! return size_to_region_num(_min_gen0_size); ! } ! size_t initial_young_region_num() { ! return size_to_region_num(_initial_gen0_size); ! } ! size_t max_young_region_num() { ! return size_to_region_num(_max_gen0_size); ! } ! }; ! ! void G1CollectorPolicy::update_young_list_size_using_newratio(size_t number_of_heap_regions) { ! assert(number_of_heap_regions > 0, "Heap must be initialized"); ! size_t young_size = number_of_heap_regions / (NewRatio + 1); ! _min_desired_young_length = young_size; ! _max_desired_young_length = young_size; ! } ! ! void G1CollectorPolicy::init() { ! // Set aside an initial future to_space. ! _g1 = G1CollectedHeap::heap(); ! ! assert(Heap_lock->owned_by_self(), "Locking discipline."); ! ! initialize_gc_policy_counters(); ! ! G1YoungGenSizer sizer; ! _min_desired_young_length = sizer.min_young_region_num(); ! _max_desired_young_length = sizer.max_young_region_num(); if (FLAG_IS_CMDLINE(NewRatio)) { if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) { warning("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio"); } else { ! // Treat NewRatio as a fixed size that is only recalculated when the heap size changes ! update_young_list_size_using_newratio(_g1->n_regions()); ! _using_new_ratio_calculations = true; } } assert(_min_desired_young_length <= _max_desired_young_length, "Invalid min/max young gen size values"); - set_adaptive_young_list_length(_min_desired_young_length < _max_desired_young_length); if (adaptive_young_list_length()) { _young_list_fixed_length = 0; } else { ! assert(_min_desired_young_length == _max_desired_young_length, "Min and max young size differ"); ! _young_list_fixed_length = _min_desired_young_length; } _free_regions_at_end_of_collection = _g1->free_regions(); update_young_list_target_length(); _prev_eden_capacity = _young_list_target_length * HeapRegion::GrainBytes; --- 416,507 ---- vm_exit_during_initialization("Invalid survivor ratio specified"); } CollectorPolicy::initialize_flags(); } ! G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true) { ! assert(G1DefaultMinNewGenPercent <= G1DefaultMaxNewGenPercent, "Min larger than max"); ! assert(G1DefaultMinNewGenPercent > 0 && G1DefaultMinNewGenPercent < 100, "Min out of bounds"); ! assert(G1DefaultMaxNewGenPercent > 0 && G1DefaultMaxNewGenPercent < 100, "Max out of bounds"); if (FLAG_IS_CMDLINE(NewRatio)) { if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) { warning("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio"); } else { ! _sizer_kind = SizerNewRatio; ! _adaptive_size = false; ! return; ! } ! } ! ! if (FLAG_IS_CMDLINE(NewSize)) { ! _min_desired_young_length = MAX2((size_t) 1, NewSize / HeapRegion::GrainBytes); ! if (FLAG_IS_CMDLINE(MaxNewSize)) { ! _max_desired_young_length = MAX2((size_t) 1, MaxNewSize / HeapRegion::GrainBytes); ! _sizer_kind = SizerMaxAndNewSize; ! _adaptive_size = _min_desired_young_length == _max_desired_young_length; ! } else { ! _sizer_kind = SizerNewSizeOnly; ! } ! } else if (FLAG_IS_CMDLINE(MaxNewSize)) { ! _max_desired_young_length = MAX2((size_t) 1, MaxNewSize / HeapRegion::GrainBytes); ! _sizer_kind = SizerMaxNewSizeOnly; } + } + + size_t G1YoungGenSizer::calculate_default_min_size(size_t new_number_of_heap_regions) { + size_t default_value = (new_number_of_heap_regions * G1DefaultMinNewGenPercent) / 100; + return MAX2((size_t)1, default_value); + } + + size_t G1YoungGenSizer::calculate_default_max_size(size_t new_number_of_heap_regions) { + size_t default_value = (new_number_of_heap_regions * G1DefaultMaxNewGenPercent) / 100; + return MAX2((size_t)1, default_value); + } + + void G1YoungGenSizer::heap_size_changed(size_t new_number_of_heap_regions) { + assert(new_number_of_heap_regions > 0, "Heap must be initialized"); + + switch (_sizer_kind) { + case SizerDefaults: + _min_desired_young_length = calculate_default_min_size(new_number_of_heap_regions); + _max_desired_young_length = calculate_default_max_size(new_number_of_heap_regions); + break; + case SizerNewSizeOnly: + _max_desired_young_length = calculate_default_max_size(new_number_of_heap_regions); + _max_desired_young_length = MAX2(_min_desired_young_length, _max_desired_young_length); + break; + case SizerMaxNewSizeOnly: + _min_desired_young_length = calculate_default_min_size(new_number_of_heap_regions); + _min_desired_young_length = MIN2(_min_desired_young_length, _max_desired_young_length); + break; + case SizerMaxAndNewSize: + // Do nothing. Values set on the command line, don't update them at runtime. + break; + case SizerNewRatio: + _min_desired_young_length = new_number_of_heap_regions / (NewRatio + 1); + _max_desired_young_length = _min_desired_young_length; + break; + default: + ShouldNotReachHere(); } assert(_min_desired_young_length <= _max_desired_young_length, "Invalid min/max young gen size values"); + } + + void G1CollectorPolicy::init() { + // Set aside an initial future to_space. + _g1 = G1CollectedHeap::heap(); + + assert(Heap_lock->owned_by_self(), "Locking discipline."); + + initialize_gc_policy_counters(); if (adaptive_young_list_length()) { _young_list_fixed_length = 0; } else { ! _young_list_fixed_length = _young_gen_sizer->min_desired_young_length(); } _free_regions_at_end_of_collection = _g1->free_regions(); update_young_list_target_length(); _prev_eden_capacity = _young_list_target_length * HeapRegion::GrainBytes;
*** 539,553 **** double reserve_regions_d = (double) new_number_of_regions * _reserve_factor; // We use ceiling so that if reserve_regions_d is > 0.0 (but // smaller than 1.0) we'll get 1. _reserve_regions = (size_t) ceil(reserve_regions_d); ! if (_using_new_ratio_calculations) { ! // -XX:NewRatio was specified so we need to update the ! // young gen length when the heap size has changed. ! update_young_list_size_using_newratio(new_number_of_regions); ! } } size_t G1CollectorPolicy::calculate_young_list_desired_min_length( size_t base_min_length) { size_t desired_min_length = 0; --- 551,561 ---- double reserve_regions_d = (double) new_number_of_regions * _reserve_factor; // We use ceiling so that if reserve_regions_d is > 0.0 (but // smaller than 1.0) we'll get 1. _reserve_regions = (size_t) ceil(reserve_regions_d); ! _young_gen_sizer->heap_size_changed(new_number_of_regions); } size_t G1CollectorPolicy::calculate_young_list_desired_min_length( size_t base_min_length) { size_t desired_min_length = 0;
*** 561,578 **** // otherwise we don't have enough info to make the prediction } } desired_min_length += base_min_length; // make sure we don't go below any user-defined minimum bound ! return MAX2(_min_desired_young_length, desired_min_length); } size_t G1CollectorPolicy::calculate_young_list_desired_max_length() { // 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 _max_desired_young_length; } void G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) { if (rs_lengths == (size_t) -1) { // if it's set to the default value (-1), we should predict it; --- 569,586 ---- // otherwise we don't have enough info to make the prediction } } 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); } size_t G1CollectorPolicy::calculate_young_list_desired_max_length() { // 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 G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) { if (rs_lengths == (size_t) -1) { // if it's set to the default value (-1), we should predict it;