src/share/vm/memory/collectorPolicy.cpp

changeset 448
183f41cf8bfe
parent 435
a61af66fc99e
child 631
d1605aabd0a1
child 777
37f87013dfd8
     1.1 --- a/src/share/vm/memory/collectorPolicy.cpp	Fri Feb 29 14:42:56 2008 -0800
     1.2 +++ b/src/share/vm/memory/collectorPolicy.cpp	Sun Mar 02 16:10:12 2008 -0800
     1.3 @@ -57,45 +57,51 @@
     1.4    // User inputs from -mx and ms are aligned
     1.5    _initial_heap_byte_size = align_size_up(Arguments::initial_heap_size(),
     1.6                                            min_alignment());
     1.7 -  _min_heap_byte_size = align_size_up(Arguments::min_heap_size(),
     1.8 -                                          min_alignment());
     1.9 -  _max_heap_byte_size = align_size_up(MaxHeapSize, max_alignment());
    1.10 +  set_min_heap_byte_size(align_size_up(Arguments::min_heap_size(),
    1.11 +                                          min_alignment()));
    1.12 +  set_max_heap_byte_size(align_size_up(MaxHeapSize, max_alignment()));
    1.13  
    1.14    // Check validity of heap parameters from launcher
    1.15 -  if (_initial_heap_byte_size == 0) {
    1.16 -    _initial_heap_byte_size = NewSize + OldSize;
    1.17 +  if (initial_heap_byte_size() == 0) {
    1.18 +    set_initial_heap_byte_size(NewSize + OldSize);
    1.19    } else {
    1.20 -    Universe::check_alignment(_initial_heap_byte_size, min_alignment(),
    1.21 +    Universe::check_alignment(initial_heap_byte_size(), min_alignment(),
    1.22                              "initial heap");
    1.23    }
    1.24 -  if (_min_heap_byte_size == 0) {
    1.25 -    _min_heap_byte_size = NewSize + OldSize;
    1.26 +  if (min_heap_byte_size() == 0) {
    1.27 +    set_min_heap_byte_size(NewSize + OldSize);
    1.28    } else {
    1.29 -    Universe::check_alignment(_min_heap_byte_size, min_alignment(),
    1.30 +    Universe::check_alignment(min_heap_byte_size(), min_alignment(),
    1.31                              "initial heap");
    1.32    }
    1.33  
    1.34    // Check heap parameter properties
    1.35 -  if (_initial_heap_byte_size < M) {
    1.36 +  if (initial_heap_byte_size() < M) {
    1.37      vm_exit_during_initialization("Too small initial heap");
    1.38    }
    1.39    // Check heap parameter properties
    1.40 -  if (_min_heap_byte_size < M) {
    1.41 +  if (min_heap_byte_size() < M) {
    1.42      vm_exit_during_initialization("Too small minimum heap");
    1.43    }
    1.44 -  if (_initial_heap_byte_size <= NewSize) {
    1.45 +  if (initial_heap_byte_size() <= NewSize) {
    1.46       // make sure there is at least some room in old space
    1.47      vm_exit_during_initialization("Too small initial heap for new size specified");
    1.48    }
    1.49 -  if (_max_heap_byte_size < _min_heap_byte_size) {
    1.50 +  if (max_heap_byte_size() < min_heap_byte_size()) {
    1.51      vm_exit_during_initialization("Incompatible minimum and maximum heap sizes specified");
    1.52    }
    1.53 -  if (_initial_heap_byte_size < _min_heap_byte_size) {
    1.54 +  if (initial_heap_byte_size() < min_heap_byte_size()) {
    1.55      vm_exit_during_initialization("Incompatible minimum and initial heap sizes specified");
    1.56    }
    1.57 -  if (_max_heap_byte_size < _initial_heap_byte_size) {
    1.58 +  if (max_heap_byte_size() < initial_heap_byte_size()) {
    1.59      vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified");
    1.60    }
    1.61 +
    1.62 +  if (PrintGCDetails && Verbose) {
    1.63 +    gclog_or_tty->print_cr("Minimum heap " SIZE_FORMAT "  Initial heap "
    1.64 +      SIZE_FORMAT "  Maximum heap " SIZE_FORMAT,
    1.65 +      min_heap_byte_size(), initial_heap_byte_size(), max_heap_byte_size());
    1.66 +  }
    1.67  }
    1.68  
    1.69  void CollectorPolicy::initialize_perm_generation(PermGen::Name pgnm) {
    1.70 @@ -128,10 +134,26 @@
    1.71  
    1.72  // GenCollectorPolicy methods.
    1.73  
    1.74 +size_t GenCollectorPolicy::scale_by_NewRatio_aligned(size_t base_size) {
    1.75 +  size_t x = base_size / (NewRatio+1);
    1.76 +  size_t new_gen_size = x > min_alignment() ?
    1.77 +                     align_size_down(x, min_alignment()) :
    1.78 +                     min_alignment();
    1.79 +  return new_gen_size;
    1.80 +}
    1.81 +
    1.82 +size_t GenCollectorPolicy::bound_minus_alignment(size_t desired_size,
    1.83 +                                                 size_t maximum_size) {
    1.84 +  size_t alignment = min_alignment();
    1.85 +  size_t max_minus = maximum_size - alignment;
    1.86 +  return desired_size < max_minus ? desired_size : max_minus;
    1.87 +}
    1.88 +
    1.89 +
    1.90  void GenCollectorPolicy::initialize_size_policy(size_t init_eden_size,
    1.91                                                  size_t init_promo_size,
    1.92                                                  size_t init_survivor_size) {
    1.93 -  double max_gc_minor_pause_sec = ((double) MaxGCMinorPauseMillis)/1000.0;
    1.94 +  const double max_gc_minor_pause_sec = ((double) MaxGCMinorPauseMillis)/1000.0;
    1.95    _size_policy = new AdaptiveSizePolicy(init_eden_size,
    1.96                                          init_promo_size,
    1.97                                          init_survivor_size,
    1.98 @@ -210,74 +232,260 @@
    1.99    assert(MaxHeapSize % max_alignment() == 0, "maximum heap alignment");
   1.100  }
   1.101  
   1.102 +// Values set on the command line win over any ergonomically
   1.103 +// set command line parameters.
   1.104 +// Ergonomic choice of parameters are done before this
   1.105 +// method is called.  Values for command line parameters such as NewSize
   1.106 +// and MaxNewSize feed those ergonomic choices into this method.
   1.107 +// This method makes the final generation sizings consistent with
   1.108 +// themselves and with overall heap sizings.
   1.109 +// In the absence of explicitly set command line flags, policies
   1.110 +// such as the use of NewRatio are used to size the generation.
   1.111  void GenCollectorPolicy::initialize_size_info() {
   1.112    CollectorPolicy::initialize_size_info();
   1.113  
   1.114 -  // Minimum sizes of the generations may be different than
   1.115 -  // the initial sizes.
   1.116 -  if (!FLAG_IS_DEFAULT(NewSize)) {
   1.117 -    _min_gen0_size = NewSize;
   1.118 +  // min_alignment() is used for alignment within a generation.
   1.119 +  // There is additional alignment done down stream for some
   1.120 +  // collectors that sometimes causes unwanted rounding up of
   1.121 +  // generations sizes.
   1.122 +
   1.123 +  // Determine maximum size of gen0
   1.124 +
   1.125 +  size_t max_new_size = 0;
   1.126 +  if (FLAG_IS_CMDLINE(MaxNewSize)) {
   1.127 +    if (MaxNewSize < min_alignment()) {
   1.128 +      max_new_size = min_alignment();
   1.129 +    } else if (MaxNewSize >= max_heap_byte_size()) {
   1.130 +      max_new_size = align_size_down(max_heap_byte_size() - min_alignment(),
   1.131 +                                     min_alignment());
   1.132 +      warning("MaxNewSize (" SIZE_FORMAT "k) is equal to or "
   1.133 +        "greater than the entire heap (" SIZE_FORMAT "k).  A "
   1.134 +        "new generation size of " SIZE_FORMAT "k will be used.",
   1.135 +        MaxNewSize/K, max_heap_byte_size()/K, max_new_size/K);
   1.136 +    } else {
   1.137 +      max_new_size = align_size_down(MaxNewSize, min_alignment());
   1.138 +    }
   1.139 +
   1.140 +  // The case for FLAG_IS_ERGO(MaxNewSize) could be treated
   1.141 +  // specially at this point to just use an ergonomically set
   1.142 +  // MaxNewSize to set max_new_size.  For cases with small
   1.143 +  // heaps such a policy often did not work because the MaxNewSize
   1.144 +  // was larger than the entire heap.  The interpretation given
   1.145 +  // to ergonomically set flags is that the flags are set
   1.146 +  // by different collectors for their own special needs but
   1.147 +  // are not allowed to badly shape the heap.  This allows the
   1.148 +  // different collectors to decide what's best for themselves
   1.149 +  // without having to factor in the overall heap shape.  It
   1.150 +  // can be the case in the future that the collectors would
   1.151 +  // only make "wise" ergonomics choices and this policy could
   1.152 +  // just accept those choices.  The choices currently made are
   1.153 +  // not always "wise".
   1.154    } else {
   1.155 -    _min_gen0_size = align_size_down(_min_heap_byte_size / (NewRatio+1),
   1.156 -                                     min_alignment());
   1.157 -    // We bound the minimum size by NewSize below (since it historically
   1.158 +    max_new_size = scale_by_NewRatio_aligned(max_heap_byte_size());
   1.159 +    // Bound the maximum size by NewSize below (since it historically
   1.160      // would have been NewSize and because the NewRatio calculation could
   1.161      // yield a size that is too small) and bound it by MaxNewSize above.
   1.162 -    // This is not always best.  The NewSize calculated by CMS (which has
   1.163 -    // a fixed minimum of 16m) can sometimes be "too" large.  Consider
   1.164 -    // the case where -Xmx32m.  The CMS calculated NewSize would be about
   1.165 -    // half the entire heap which seems too large.  But the counter
   1.166 -    // example is seen when the client defaults for NewRatio are used.
   1.167 -    // An initial young generation size of 640k was observed
   1.168 -    // with -Xmx128m -XX:MaxNewSize=32m when NewSize was not used
   1.169 -    // as a lower bound as with
   1.170 -    // _min_gen0_size = MIN2(_min_gen0_size, MaxNewSize);
   1.171 -    // and 640k seemed too small a young generation.
   1.172 -    _min_gen0_size = MIN2(MAX2(_min_gen0_size, NewSize), MaxNewSize);
   1.173 +    // Ergonomics plays here by previously calculating the desired
   1.174 +    // NewSize and MaxNewSize.
   1.175 +    max_new_size = MIN2(MAX2(max_new_size, NewSize), MaxNewSize);
   1.176 +  }
   1.177 +  assert(max_new_size > 0, "All paths should set max_new_size");
   1.178 +
   1.179 +  // Given the maximum gen0 size, determine the initial and
   1.180 +  // minimum sizes.
   1.181 +
   1.182 +  if (max_heap_byte_size() == min_heap_byte_size()) {
   1.183 +    // The maximum and minimum heap sizes are the same so
   1.184 +    // the generations minimum and initial must be the
   1.185 +    // same as its maximum.
   1.186 +    set_min_gen0_size(max_new_size);
   1.187 +    set_initial_gen0_size(max_new_size);
   1.188 +    set_max_gen0_size(max_new_size);
   1.189 +  } else {
   1.190 +    size_t desired_new_size = 0;
   1.191 +    if (!FLAG_IS_DEFAULT(NewSize)) {
   1.192 +      // If NewSize is set ergonomically (for example by cms), it
   1.193 +      // would make sense to use it.  If it is used, also use it
   1.194 +      // to set the initial size.  Although there is no reason
   1.195 +      // the minimum size and the initial size have to be the same,
   1.196 +      // the current implementation gets into trouble during the calculation
   1.197 +      // of the tenured generation sizes if they are different.
   1.198 +      // Note that this makes the initial size and the minimum size
   1.199 +      // generally small compared to the NewRatio calculation.
   1.200 +      _min_gen0_size = NewSize;
   1.201 +      desired_new_size = NewSize;
   1.202 +      max_new_size = MAX2(max_new_size, NewSize);
   1.203 +    } else {
   1.204 +      // For the case where NewSize is the default, use NewRatio
   1.205 +      // to size the minimum and initial generation sizes.
   1.206 +      // Use the default NewSize as the floor for these values.  If
   1.207 +      // NewRatio is overly large, the resulting sizes can be too
   1.208 +      // small.
   1.209 +      _min_gen0_size = MAX2(scale_by_NewRatio_aligned(min_heap_byte_size()),
   1.210 +                          NewSize);
   1.211 +      desired_new_size =
   1.212 +        MAX2(scale_by_NewRatio_aligned(initial_heap_byte_size()),
   1.213 +             NewSize);
   1.214 +    }
   1.215 +
   1.216 +    assert(_min_gen0_size > 0, "Sanity check");
   1.217 +    set_initial_gen0_size(desired_new_size);
   1.218 +    set_max_gen0_size(max_new_size);
   1.219 +
   1.220 +    // At this point the desirable initial and minimum sizes have been
   1.221 +    // determined without regard to the maximum sizes.
   1.222 +
   1.223 +    // Bound the sizes by the corresponding overall heap sizes.
   1.224 +    set_min_gen0_size(
   1.225 +      bound_minus_alignment(_min_gen0_size, min_heap_byte_size()));
   1.226 +    set_initial_gen0_size(
   1.227 +      bound_minus_alignment(_initial_gen0_size, initial_heap_byte_size()));
   1.228 +    set_max_gen0_size(
   1.229 +      bound_minus_alignment(_max_gen0_size, max_heap_byte_size()));
   1.230 +
   1.231 +    // At this point all three sizes have been checked against the
   1.232 +    // maximum sizes but have not been checked for consistency
   1.233 +    // amoung the three.
   1.234 +
   1.235 +    // Final check min <= initial <= max
   1.236 +    set_min_gen0_size(MIN2(_min_gen0_size, _max_gen0_size));
   1.237 +    set_initial_gen0_size(
   1.238 +      MAX2(MIN2(_initial_gen0_size, _max_gen0_size), _min_gen0_size));
   1.239 +    set_min_gen0_size(MIN2(_min_gen0_size, _initial_gen0_size));
   1.240    }
   1.241  
   1.242 -  // Parameters are valid, compute area sizes.
   1.243 -  size_t max_new_size = align_size_down(_max_heap_byte_size / (NewRatio+1),
   1.244 -                                        min_alignment());
   1.245 -  max_new_size = MIN2(MAX2(max_new_size, _min_gen0_size), MaxNewSize);
   1.246 +  if (PrintGCDetails && Verbose) {
   1.247 +    gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT "  Initial gen0 "
   1.248 +      SIZE_FORMAT "  Maximum gen0 " SIZE_FORMAT,
   1.249 +      min_gen0_size(), initial_gen0_size(), max_gen0_size());
   1.250 +  }
   1.251 +}
   1.252  
   1.253 -  // desired_new_size is used to set the initial size.  The
   1.254 -  // initial size must be greater than the minimum size.
   1.255 -  size_t desired_new_size =
   1.256 -    align_size_down(_initial_heap_byte_size / (NewRatio+1),
   1.257 -                  min_alignment());
   1.258 +// Call this method during the sizing of the gen1 to make
   1.259 +// adjustments to gen0 because of gen1 sizing policy.  gen0 initially has
   1.260 +// the most freedom in sizing because it is done before the
   1.261 +// policy for gen1 is applied.  Once gen1 policies have been applied,
   1.262 +// there may be conflicts in the shape of the heap and this method
   1.263 +// is used to make the needed adjustments.  The application of the
   1.264 +// policies could be more sophisticated (iterative for example) but
   1.265 +// keeping it simple also seems a worthwhile goal.
   1.266 +bool TwoGenerationCollectorPolicy::adjust_gen0_sizes(size_t* gen0_size_ptr,
   1.267 +                                                     size_t* gen1_size_ptr,
   1.268 +                                                     size_t heap_size,
   1.269 +                                                     size_t min_gen0_size) {
   1.270 +  bool result = false;
   1.271 +  if ((*gen1_size_ptr + *gen0_size_ptr) > heap_size) {
   1.272 +    if (((*gen0_size_ptr + OldSize) > heap_size) &&
   1.273 +       (heap_size - min_gen0_size) >= min_alignment()) {
   1.274 +      // Adjust gen0 down to accomodate OldSize
   1.275 +      *gen0_size_ptr = heap_size - min_gen0_size;
   1.276 +      *gen0_size_ptr =
   1.277 +        MAX2((uintx)align_size_down(*gen0_size_ptr, min_alignment()),
   1.278 +             min_alignment());
   1.279 +      assert(*gen0_size_ptr > 0, "Min gen0 is too large");
   1.280 +      result = true;
   1.281 +    } else {
   1.282 +      *gen1_size_ptr = heap_size - *gen0_size_ptr;
   1.283 +      *gen1_size_ptr =
   1.284 +        MAX2((uintx)align_size_down(*gen1_size_ptr, min_alignment()),
   1.285 +                       min_alignment());
   1.286 +    }
   1.287 +  }
   1.288 +  return result;
   1.289 +}
   1.290  
   1.291 -  size_t new_size = MIN2(MAX2(desired_new_size, _min_gen0_size), max_new_size);
   1.292 -
   1.293 -  _initial_gen0_size = new_size;
   1.294 -  _max_gen0_size = max_new_size;
   1.295 -}
   1.296 +// Minimum sizes of the generations may be different than
   1.297 +// the initial sizes.  An inconsistently is permitted here
   1.298 +// in the total size that can be specified explicitly by
   1.299 +// command line specification of OldSize and NewSize and
   1.300 +// also a command line specification of -Xms.  Issue a warning
   1.301 +// but allow the values to pass.
   1.302  
   1.303  void TwoGenerationCollectorPolicy::initialize_size_info() {
   1.304    GenCollectorPolicy::initialize_size_info();
   1.305  
   1.306 -  // Minimum sizes of the generations may be different than
   1.307 -  // the initial sizes.  An inconsistently is permitted here
   1.308 -  // in the total size that can be specified explicitly by
   1.309 -  // command line specification of OldSize and NewSize and
   1.310 -  // also a command line specification of -Xms.  Issue a warning
   1.311 -  // but allow the values to pass.
   1.312 -  if (!FLAG_IS_DEFAULT(OldSize)) {
   1.313 -    _min_gen1_size = OldSize;
   1.314 +  // At this point the minimum, initial and maximum sizes
   1.315 +  // of the overall heap and of gen0 have been determined.
   1.316 +  // The maximum gen1 size can be determined from the maximum gen0
   1.317 +  // and maximum heap size since not explicit flags exits
   1.318 +  // for setting the gen1 maximum.
   1.319 +  _max_gen1_size = max_heap_byte_size() - _max_gen0_size;
   1.320 +  _max_gen1_size =
   1.321 +    MAX2((uintx)align_size_down(_max_gen1_size, min_alignment()),
   1.322 +         min_alignment());
   1.323 +  // If no explicit command line flag has been set for the
   1.324 +  // gen1 size, use what is left for gen1.
   1.325 +  if (FLAG_IS_DEFAULT(OldSize) || FLAG_IS_ERGO(OldSize)) {
   1.326 +    // The user has not specified any value or ergonomics
   1.327 +    // has chosen a value (which may or may not be consistent
   1.328 +    // with the overall heap size).  In either case make
   1.329 +    // the minimum, maximum and initial sizes consistent
   1.330 +    // with the gen0 sizes and the overall heap sizes.
   1.331 +    assert(min_heap_byte_size() > _min_gen0_size,
   1.332 +      "gen0 has an unexpected minimum size");
   1.333 +    set_min_gen1_size(min_heap_byte_size() - min_gen0_size());
   1.334 +    set_min_gen1_size(
   1.335 +      MAX2((uintx)align_size_down(_min_gen1_size, min_alignment()),
   1.336 +           min_alignment()));
   1.337 +    set_initial_gen1_size(initial_heap_byte_size() - initial_gen0_size());
   1.338 +    set_initial_gen1_size(
   1.339 +      MAX2((uintx)align_size_down(_initial_gen1_size, min_alignment()),
   1.340 +           min_alignment()));
   1.341 +
   1.342 +  } else {
   1.343 +    // It's been explicitly set on the command line.  Use the
   1.344 +    // OldSize and then determine the consequences.
   1.345 +    set_min_gen1_size(OldSize);
   1.346 +    set_initial_gen1_size(OldSize);
   1.347 +
   1.348 +    // If the user has explicitly set an OldSize that is inconsistent
   1.349 +    // with other command line flags, issue a warning.
   1.350      // The generation minimums and the overall heap mimimum should
   1.351      // be within one heap alignment.
   1.352 -    if ((_min_gen1_size + _min_gen0_size + max_alignment()) <
   1.353 -         _min_heap_byte_size) {
   1.354 +    if ((_min_gen1_size + _min_gen0_size + min_alignment()) <
   1.355 +           min_heap_byte_size()) {
   1.356        warning("Inconsistency between minimum heap size and minimum "
   1.357 -        "generation sizes: using min heap = " SIZE_FORMAT,
   1.358 -        _min_heap_byte_size);
   1.359 +          "generation sizes: using minimum heap = " SIZE_FORMAT,
   1.360 +          min_heap_byte_size());
   1.361      }
   1.362 -  } else {
   1.363 -    _min_gen1_size = _min_heap_byte_size - _min_gen0_size;
   1.364 +    if ((OldSize > _max_gen1_size)) {
   1.365 +      warning("Inconsistency between maximum heap size and maximum "
   1.366 +          "generation sizes: using maximum heap = " SIZE_FORMAT
   1.367 +          " -XX:OldSize flag is being ignored",
   1.368 +          max_heap_byte_size());
   1.369    }
   1.370 +    // If there is an inconsistency between the OldSize and the minimum and/or
   1.371 +    // initial size of gen0, since OldSize was explicitly set, OldSize wins.
   1.372 +    if (adjust_gen0_sizes(&_min_gen0_size, &_min_gen1_size,
   1.373 +                          min_heap_byte_size(), OldSize)) {
   1.374 +      if (PrintGCDetails && Verbose) {
   1.375 +        gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT "  Initial gen0 "
   1.376 +              SIZE_FORMAT "  Maximum gen0 " SIZE_FORMAT,
   1.377 +              min_gen0_size(), initial_gen0_size(), max_gen0_size());
   1.378 +      }
   1.379 +    }
   1.380 +    // Initial size
   1.381 +    if (adjust_gen0_sizes(&_initial_gen0_size, &_initial_gen1_size,
   1.382 +                         initial_heap_byte_size(), OldSize)) {
   1.383 +      if (PrintGCDetails && Verbose) {
   1.384 +        gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT "  Initial gen0 "
   1.385 +          SIZE_FORMAT "  Maximum gen0 " SIZE_FORMAT,
   1.386 +          min_gen0_size(), initial_gen0_size(), max_gen0_size());
   1.387 +      }
   1.388 +    }
   1.389 +  }
   1.390 +  // Enforce the maximum gen1 size.
   1.391 +  set_min_gen1_size(MIN2(_min_gen1_size, _max_gen1_size));
   1.392  
   1.393 -  _initial_gen1_size = _initial_heap_byte_size - _initial_gen0_size;
   1.394 -  _max_gen1_size = _max_heap_byte_size - _max_gen0_size;
   1.395 +  // Check that min gen1 <= initial gen1 <= max gen1
   1.396 +  set_initial_gen1_size(MAX2(_initial_gen1_size, _min_gen1_size));
   1.397 +  set_initial_gen1_size(MIN2(_initial_gen1_size, _max_gen1_size));
   1.398 +
   1.399 +  if (PrintGCDetails && Verbose) {
   1.400 +    gclog_or_tty->print_cr("Minimum gen1 " SIZE_FORMAT "  Initial gen1 "
   1.401 +      SIZE_FORMAT "  Maximum gen1 " SIZE_FORMAT,
   1.402 +      min_gen1_size(), initial_gen1_size(), max_gen1_size());
   1.403 +  }
   1.404  }
   1.405  
   1.406  HeapWord* GenCollectorPolicy::mem_allocate_work(size_t size,

mercurial