7113021: G1: automatically enable young gen size auto-tuning when -Xms==-Xmx

Wed, 21 Dec 2011 22:13:31 +0100

author
brutisso
date
Wed, 21 Dec 2011 22:13:31 +0100
changeset 3358
1cbe7978b021
parent 3357
441e946dc1af
child 3359
7faca6dfa2ed

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, johnc

src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1_globals.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Wed Dec 14 13:34:57 2011 -0800
     1.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Wed Dec 21 22:13:31 2011 +0100
     1.3 @@ -136,7 +136,6 @@
     1.4    _stop_world_start(0.0),
     1.5    _all_stop_world_times_ms(new NumberSeq()),
     1.6    _all_yield_times_ms(new NumberSeq()),
     1.7 -  _using_new_ratio_calculations(false),
     1.8  
     1.9    _summary(new Summary()),
    1.10  
    1.11 @@ -409,11 +408,7 @@
    1.12  
    1.13    initialize_all();
    1.14    _collectionSetChooser = new CollectionSetChooser();
    1.15 -}
    1.16 -
    1.17 -// Increment "i", mod "len"
    1.18 -static void inc_mod(int& i, int len) {
    1.19 -  i++; if (i == len) i = 0;
    1.20 +  _young_gen_sizer = new G1YoungGenSizer(); // Must be after call to initialize_flags
    1.21  }
    1.22  
    1.23  void G1CollectorPolicy::initialize_flags() {
    1.24 @@ -425,71 +420,88 @@
    1.25    CollectorPolicy::initialize_flags();
    1.26  }
    1.27  
    1.28 -// The easiest way to deal with the parsing of the NewSize /
    1.29 -// MaxNewSize / etc. parameteres is to re-use the code in the
    1.30 -// TwoGenerationCollectorPolicy class. This is similar to what
    1.31 -// ParallelScavenge does with its GenerationSizer class (see
    1.32 -// ParallelScavengeHeap::initialize()). We might change this in the
    1.33 -// future, but it's a good start.
    1.34 -class G1YoungGenSizer : public TwoGenerationCollectorPolicy {
    1.35 -private:
    1.36 -  size_t size_to_region_num(size_t byte_size) {
    1.37 -    return MAX2((size_t) 1, byte_size / HeapRegion::GrainBytes);
    1.38 -  }
    1.39 -
    1.40 -public:
    1.41 -  G1YoungGenSizer() {
    1.42 -    initialize_flags();
    1.43 -    initialize_size_info();
    1.44 -  }
    1.45 -  size_t min_young_region_num() {
    1.46 -    return size_to_region_num(_min_gen0_size);
    1.47 -  }
    1.48 -  size_t initial_young_region_num() {
    1.49 -    return size_to_region_num(_initial_gen0_size);
    1.50 -  }
    1.51 -  size_t max_young_region_num() {
    1.52 -    return size_to_region_num(_max_gen0_size);
    1.53 -  }
    1.54 -};
    1.55 -
    1.56 -void G1CollectorPolicy::update_young_list_size_using_newratio(size_t number_of_heap_regions) {
    1.57 -  assert(number_of_heap_regions > 0, "Heap must be initialized");
    1.58 -  size_t young_size = number_of_heap_regions / (NewRatio + 1);
    1.59 -  _min_desired_young_length = young_size;
    1.60 -  _max_desired_young_length = young_size;
    1.61 -}
    1.62 -
    1.63 -void G1CollectorPolicy::init() {
    1.64 -  // Set aside an initial future to_space.
    1.65 -  _g1 = G1CollectedHeap::heap();
    1.66 -
    1.67 -  assert(Heap_lock->owned_by_self(), "Locking discipline.");
    1.68 -
    1.69 -  initialize_gc_policy_counters();
    1.70 -
    1.71 -  G1YoungGenSizer sizer;
    1.72 -  _min_desired_young_length = sizer.min_young_region_num();
    1.73 -  _max_desired_young_length = sizer.max_young_region_num();
    1.74 +G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true) {
    1.75 +  assert(G1DefaultMinNewGenPercent <= G1DefaultMaxNewGenPercent, "Min larger than max");
    1.76 +  assert(G1DefaultMinNewGenPercent > 0 && G1DefaultMinNewGenPercent < 100, "Min out of bounds");
    1.77 +  assert(G1DefaultMaxNewGenPercent > 0 && G1DefaultMaxNewGenPercent < 100, "Max out of bounds");
    1.78  
    1.79    if (FLAG_IS_CMDLINE(NewRatio)) {
    1.80      if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) {
    1.81        warning("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio");
    1.82      } else {
    1.83 -      // Treat NewRatio as a fixed size that is only recalculated when the heap size changes
    1.84 -      update_young_list_size_using_newratio(_g1->n_regions());
    1.85 -      _using_new_ratio_calculations = true;
    1.86 +      _sizer_kind = SizerNewRatio;
    1.87 +      _adaptive_size = false;
    1.88 +      return;
    1.89      }
    1.90    }
    1.91  
    1.92 +  if (FLAG_IS_CMDLINE(NewSize)) {
    1.93 +     _min_desired_young_length = MAX2((size_t) 1, NewSize / HeapRegion::GrainBytes);
    1.94 +    if (FLAG_IS_CMDLINE(MaxNewSize)) {
    1.95 +      _max_desired_young_length = MAX2((size_t) 1, MaxNewSize / HeapRegion::GrainBytes);
    1.96 +      _sizer_kind = SizerMaxAndNewSize;
    1.97 +      _adaptive_size = _min_desired_young_length == _max_desired_young_length;
    1.98 +    } else {
    1.99 +      _sizer_kind = SizerNewSizeOnly;
   1.100 +    }
   1.101 +  } else if (FLAG_IS_CMDLINE(MaxNewSize)) {
   1.102 +    _max_desired_young_length = MAX2((size_t) 1, MaxNewSize / HeapRegion::GrainBytes);
   1.103 +    _sizer_kind = SizerMaxNewSizeOnly;
   1.104 +  }
   1.105 +}
   1.106 +
   1.107 +size_t G1YoungGenSizer::calculate_default_min_length(size_t new_number_of_heap_regions) {
   1.108 +  size_t default_value = (new_number_of_heap_regions * G1DefaultMinNewGenPercent) / 100;
   1.109 +  return MAX2((size_t)1, default_value);
   1.110 +}
   1.111 +
   1.112 +size_t G1YoungGenSizer::calculate_default_max_length(size_t new_number_of_heap_regions) {
   1.113 +  size_t default_value = (new_number_of_heap_regions * G1DefaultMaxNewGenPercent) / 100;
   1.114 +  return MAX2((size_t)1, default_value);
   1.115 +}
   1.116 +
   1.117 +void G1YoungGenSizer::heap_size_changed(size_t new_number_of_heap_regions) {
   1.118 +  assert(new_number_of_heap_regions > 0, "Heap must be initialized");
   1.119 +
   1.120 +  switch (_sizer_kind) {
   1.121 +    case SizerDefaults:
   1.122 +      _min_desired_young_length = calculate_default_min_length(new_number_of_heap_regions);
   1.123 +      _max_desired_young_length = calculate_default_max_length(new_number_of_heap_regions);
   1.124 +      break;
   1.125 +    case SizerNewSizeOnly:
   1.126 +      _max_desired_young_length = calculate_default_max_length(new_number_of_heap_regions);
   1.127 +      _max_desired_young_length = MAX2(_min_desired_young_length, _max_desired_young_length);
   1.128 +      break;
   1.129 +    case SizerMaxNewSizeOnly:
   1.130 +      _min_desired_young_length = calculate_default_min_length(new_number_of_heap_regions);
   1.131 +      _min_desired_young_length = MIN2(_min_desired_young_length, _max_desired_young_length);
   1.132 +      break;
   1.133 +    case SizerMaxAndNewSize:
   1.134 +      // Do nothing. Values set on the command line, don't update them at runtime.
   1.135 +      break;
   1.136 +    case SizerNewRatio:
   1.137 +      _min_desired_young_length = new_number_of_heap_regions / (NewRatio + 1);
   1.138 +      _max_desired_young_length = _min_desired_young_length;
   1.139 +      break;
   1.140 +    default:
   1.141 +      ShouldNotReachHere();
   1.142 +  }
   1.143 +
   1.144    assert(_min_desired_young_length <= _max_desired_young_length, "Invalid min/max young gen size values");
   1.145 -
   1.146 -  set_adaptive_young_list_length(_min_desired_young_length < _max_desired_young_length);
   1.147 +}
   1.148 +
   1.149 +void G1CollectorPolicy::init() {
   1.150 +  // Set aside an initial future to_space.
   1.151 +  _g1 = G1CollectedHeap::heap();
   1.152 +
   1.153 +  assert(Heap_lock->owned_by_self(), "Locking discipline.");
   1.154 +
   1.155 +  initialize_gc_policy_counters();
   1.156 +
   1.157    if (adaptive_young_list_length()) {
   1.158      _young_list_fixed_length = 0;
   1.159    } else {
   1.160 -    assert(_min_desired_young_length == _max_desired_young_length, "Min and max young size differ");
   1.161 -    _young_list_fixed_length = _min_desired_young_length;
   1.162 +    _young_list_fixed_length = _young_gen_sizer->min_desired_young_length();
   1.163    }
   1.164    _free_regions_at_end_of_collection = _g1->free_regions();
   1.165    update_young_list_target_length();
   1.166 @@ -543,11 +555,7 @@
   1.167    // smaller than 1.0) we'll get 1.
   1.168    _reserve_regions = (size_t) ceil(reserve_regions_d);
   1.169  
   1.170 -  if (_using_new_ratio_calculations) {
   1.171 -    // -XX:NewRatio was specified so we need to update the
   1.172 -    // young gen length when the heap size has changed.
   1.173 -    update_young_list_size_using_newratio(new_number_of_regions);
   1.174 -  }
   1.175 +  _young_gen_sizer->heap_size_changed(new_number_of_regions);
   1.176  }
   1.177  
   1.178  size_t G1CollectorPolicy::calculate_young_list_desired_min_length(
   1.179 @@ -565,14 +573,14 @@
   1.180    }
   1.181    desired_min_length += base_min_length;
   1.182    // make sure we don't go below any user-defined minimum bound
   1.183 -  return MAX2(_min_desired_young_length, desired_min_length);
   1.184 +  return MAX2(_young_gen_sizer->min_desired_young_length(), desired_min_length);
   1.185  }
   1.186  
   1.187  size_t G1CollectorPolicy::calculate_young_list_desired_max_length() {
   1.188    // Here, we might want to also take into account any additional
   1.189    // constraints (i.e., user-defined minimum bound). Currently, we
   1.190    // effectively don't set this bound.
   1.191 -  return _max_desired_young_length;
   1.192 +  return _young_gen_sizer->max_desired_young_length();
   1.193  }
   1.194  
   1.195  void G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) {
     2.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Wed Dec 14 13:34:57 2011 -0800
     2.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp	Wed Dec 21 22:13:31 2011 +0100
     2.3 @@ -83,6 +83,72 @@
     2.4    virtual MainBodySummary*    main_body_summary()    { return this; }
     2.5  };
     2.6  
     2.7 +// There are three command line options related to the young gen size:
     2.8 +// NewSize, MaxNewSize and NewRatio (There is also -Xmn, but that is
     2.9 +// just a short form for NewSize==MaxNewSize). G1 will use its internal
    2.10 +// heuristics to calculate the actual young gen size, so these options
    2.11 +// basically only limit the range within which G1 can pick a young gen
    2.12 +// size. Also, these are general options taking byte sizes. G1 will
    2.13 +// internally work with a number of regions instead. So, some rounding
    2.14 +// will occur.
    2.15 +//
    2.16 +// If nothing related to the the young gen size is set on the command
    2.17 +// line we should allow the young gen to be between
    2.18 +// G1DefaultMinNewGenPercent and G1DefaultMaxNewGenPercent of the
    2.19 +// heap size. This means that every time the heap size changes the
    2.20 +// limits for the young gen size will be updated.
    2.21 +//
    2.22 +// If only -XX:NewSize is set we should use the specified value as the
    2.23 +// minimum size for young gen. Still using G1DefaultMaxNewGenPercent
    2.24 +// of the heap as maximum.
    2.25 +//
    2.26 +// If only -XX:MaxNewSize is set we should use the specified value as the
    2.27 +// maximum size for young gen. Still using G1DefaultMinNewGenPercent
    2.28 +// of the heap as minimum.
    2.29 +//
    2.30 +// If -XX:NewSize and -XX:MaxNewSize are both specified we use these values.
    2.31 +// No updates when the heap size changes. There is a special case when
    2.32 +// NewSize==MaxNewSize. This is interpreted as "fixed" and will use a
    2.33 +// different heuristic for calculating the collection set when we do mixed
    2.34 +// collection.
    2.35 +//
    2.36 +// If only -XX:NewRatio is set we should use the specified ratio of the heap
    2.37 +// as both min and max. This will be interpreted as "fixed" just like the
    2.38 +// NewSize==MaxNewSize case above. But we will update the min and max
    2.39 +// everytime the heap size changes.
    2.40 +//
    2.41 +// NewSize and MaxNewSize override NewRatio. So, NewRatio is ignored if it is
    2.42 +// combined with either NewSize or MaxNewSize. (A warning message is printed.)
    2.43 +class G1YoungGenSizer : public CHeapObj {
    2.44 +private:
    2.45 +  enum SizerKind {
    2.46 +    SizerDefaults,
    2.47 +    SizerNewSizeOnly,
    2.48 +    SizerMaxNewSizeOnly,
    2.49 +    SizerMaxAndNewSize,
    2.50 +    SizerNewRatio
    2.51 +  };
    2.52 +  SizerKind _sizer_kind;
    2.53 +  size_t _min_desired_young_length;
    2.54 +  size_t _max_desired_young_length;
    2.55 +  bool _adaptive_size;
    2.56 +  size_t calculate_default_min_length(size_t new_number_of_heap_regions);
    2.57 +  size_t calculate_default_max_length(size_t new_number_of_heap_regions);
    2.58 +
    2.59 +public:
    2.60 +  G1YoungGenSizer();
    2.61 +  void heap_size_changed(size_t new_number_of_heap_regions);
    2.62 +  size_t min_desired_young_length() {
    2.63 +    return _min_desired_young_length;
    2.64 +  }
    2.65 +  size_t max_desired_young_length() {
    2.66 +    return _max_desired_young_length;
    2.67 +  }
    2.68 +  bool adaptive_young_list_length() {
    2.69 +    return _adaptive_size;
    2.70 +  }
    2.71 +};
    2.72 +
    2.73  class G1CollectorPolicy: public CollectorPolicy {
    2.74  private:
    2.75    // either equal to the number of parallel threads, if ParallelGCThreads
    2.76 @@ -167,9 +233,6 @@
    2.77    // indicates whether we are in young or mixed GC mode
    2.78    bool _gcs_are_young;
    2.79  
    2.80 -  // if true, then it tries to dynamically adjust the length of the
    2.81 -  // young list
    2.82 -  bool _adaptive_young_list_length;
    2.83    size_t _young_list_target_length;
    2.84    size_t _young_list_fixed_length;
    2.85    size_t _prev_eden_capacity; // used for logging
    2.86 @@ -227,9 +290,7 @@
    2.87  
    2.88    TruncatedSeq* _young_gc_eff_seq;
    2.89  
    2.90 -  bool   _using_new_ratio_calculations;
    2.91 -  size_t _min_desired_young_length; // as set on the command line or default calculations
    2.92 -  size_t _max_desired_young_length; // as set on the command line or default calculations
    2.93 +  G1YoungGenSizer* _young_gen_sizer;
    2.94  
    2.95    size_t _eden_cset_region_length;
    2.96    size_t _survivor_cset_region_length;
    2.97 @@ -695,8 +756,6 @@
    2.98    // Count the number of bytes used in the CS.
    2.99    void count_CS_bytes_used();
   2.100  
   2.101 -  void update_young_list_size_using_newratio(size_t number_of_heap_regions);
   2.102 -
   2.103  public:
   2.104  
   2.105    G1CollectorPolicy();
   2.106 @@ -723,8 +782,6 @@
   2.107    // This should be called after the heap is resized.
   2.108    void record_new_heap_size(size_t new_number_of_regions);
   2.109  
   2.110 -public:
   2.111 -
   2.112    void init();
   2.113  
   2.114    // Create jstat counters for the policy.
   2.115 @@ -1014,10 +1071,7 @@
   2.116    }
   2.117  
   2.118    bool adaptive_young_list_length() {
   2.119 -    return _adaptive_young_list_length;
   2.120 -  }
   2.121 -  void set_adaptive_young_list_length(bool adaptive_young_list_length) {
   2.122 -    _adaptive_young_list_length = adaptive_young_list_length;
   2.123 +    return _young_gen_sizer->adaptive_young_list_length();
   2.124    }
   2.125  
   2.126    inline double get_gc_eff_factor() {
     3.1 --- a/src/share/vm/gc_implementation/g1/g1_globals.hpp	Wed Dec 14 13:34:57 2011 -0800
     3.2 +++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp	Wed Dec 21 22:13:31 2011 +0100
     3.3 @@ -289,7 +289,15 @@
     3.4                                                                              \
     3.5    develop(uintx, G1ConcMarkForceOverflow, 0,                                \
     3.6            "The number of times we'll force an overflow during "             \
     3.7 -          "concurrent marking")
     3.8 +          "concurrent marking")                                             \
     3.9 +                                                                            \
    3.10 +  develop(uintx, G1DefaultMinNewGenPercent, 20,                             \
    3.11 +          "Percentage (0-100) of the heap size to use as minimum "          \
    3.12 +          "young gen size.")                                                \
    3.13 +                                                                            \
    3.14 +  develop(uintx, G1DefaultMaxNewGenPercent, 50,                             \
    3.15 +          "Percentage (0-100) of the heap size to use as maximum "          \
    3.16 +          "young gen size.")
    3.17  
    3.18  G1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG)
    3.19  

mercurial