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,