Mercurial > hg > truffle
comparison src/share/vm/memory/collectorPolicy.cpp @ 13:183f41cf8bfe
6557851: CMS: ergonomics defaults are not set with FLAG_SET_ERGO
Summary: Default values set by cms ergonomics are set with FLAG_SET_DEFAULT so down stream the values look like the default values and affect how later parameters are set. Set these values with FLAG_SET_ERGO instead and adjust how later parameters are interpreted.
Reviewed-by: iveresov, apetrusenko, pbk, ysr
author | jmasa |
---|---|
date | Sun, 02 Mar 2008 16:10:12 -0800 |
parents | a61af66fc99e |
children | d1605aabd0a1 37f87013dfd8 |
comparison
equal
deleted
inserted
replaced
12:6432c3bb6240 | 13:183f41cf8bfe |
---|---|
55 | 55 |
56 void CollectorPolicy::initialize_size_info() { | 56 void CollectorPolicy::initialize_size_info() { |
57 // User inputs from -mx and ms are aligned | 57 // User inputs from -mx and ms are aligned |
58 _initial_heap_byte_size = align_size_up(Arguments::initial_heap_size(), | 58 _initial_heap_byte_size = align_size_up(Arguments::initial_heap_size(), |
59 min_alignment()); | 59 min_alignment()); |
60 _min_heap_byte_size = align_size_up(Arguments::min_heap_size(), | 60 set_min_heap_byte_size(align_size_up(Arguments::min_heap_size(), |
61 min_alignment()); | 61 min_alignment())); |
62 _max_heap_byte_size = align_size_up(MaxHeapSize, max_alignment()); | 62 set_max_heap_byte_size(align_size_up(MaxHeapSize, max_alignment())); |
63 | 63 |
64 // Check validity of heap parameters from launcher | 64 // Check validity of heap parameters from launcher |
65 if (_initial_heap_byte_size == 0) { | 65 if (initial_heap_byte_size() == 0) { |
66 _initial_heap_byte_size = NewSize + OldSize; | 66 set_initial_heap_byte_size(NewSize + OldSize); |
67 } else { | 67 } else { |
68 Universe::check_alignment(_initial_heap_byte_size, min_alignment(), | 68 Universe::check_alignment(initial_heap_byte_size(), min_alignment(), |
69 "initial heap"); | 69 "initial heap"); |
70 } | 70 } |
71 if (_min_heap_byte_size == 0) { | 71 if (min_heap_byte_size() == 0) { |
72 _min_heap_byte_size = NewSize + OldSize; | 72 set_min_heap_byte_size(NewSize + OldSize); |
73 } else { | 73 } else { |
74 Universe::check_alignment(_min_heap_byte_size, min_alignment(), | 74 Universe::check_alignment(min_heap_byte_size(), min_alignment(), |
75 "initial heap"); | 75 "initial heap"); |
76 } | 76 } |
77 | 77 |
78 // Check heap parameter properties | 78 // Check heap parameter properties |
79 if (_initial_heap_byte_size < M) { | 79 if (initial_heap_byte_size() < M) { |
80 vm_exit_during_initialization("Too small initial heap"); | 80 vm_exit_during_initialization("Too small initial heap"); |
81 } | 81 } |
82 // Check heap parameter properties | 82 // Check heap parameter properties |
83 if (_min_heap_byte_size < M) { | 83 if (min_heap_byte_size() < M) { |
84 vm_exit_during_initialization("Too small minimum heap"); | 84 vm_exit_during_initialization("Too small minimum heap"); |
85 } | 85 } |
86 if (_initial_heap_byte_size <= NewSize) { | 86 if (initial_heap_byte_size() <= NewSize) { |
87 // make sure there is at least some room in old space | 87 // make sure there is at least some room in old space |
88 vm_exit_during_initialization("Too small initial heap for new size specified"); | 88 vm_exit_during_initialization("Too small initial heap for new size specified"); |
89 } | 89 } |
90 if (_max_heap_byte_size < _min_heap_byte_size) { | 90 if (max_heap_byte_size() < min_heap_byte_size()) { |
91 vm_exit_during_initialization("Incompatible minimum and maximum heap sizes specified"); | 91 vm_exit_during_initialization("Incompatible minimum and maximum heap sizes specified"); |
92 } | 92 } |
93 if (_initial_heap_byte_size < _min_heap_byte_size) { | 93 if (initial_heap_byte_size() < min_heap_byte_size()) { |
94 vm_exit_during_initialization("Incompatible minimum and initial heap sizes specified"); | 94 vm_exit_during_initialization("Incompatible minimum and initial heap sizes specified"); |
95 } | 95 } |
96 if (_max_heap_byte_size < _initial_heap_byte_size) { | 96 if (max_heap_byte_size() < initial_heap_byte_size()) { |
97 vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified"); | 97 vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified"); |
98 } | |
99 | |
100 if (PrintGCDetails && Verbose) { | |
101 gclog_or_tty->print_cr("Minimum heap " SIZE_FORMAT " Initial heap " | |
102 SIZE_FORMAT " Maximum heap " SIZE_FORMAT, | |
103 min_heap_byte_size(), initial_heap_byte_size(), max_heap_byte_size()); | |
98 } | 104 } |
99 } | 105 } |
100 | 106 |
101 void CollectorPolicy::initialize_perm_generation(PermGen::Name pgnm) { | 107 void CollectorPolicy::initialize_perm_generation(PermGen::Name pgnm) { |
102 _permanent_generation = | 108 _permanent_generation = |
126 } | 132 } |
127 } | 133 } |
128 | 134 |
129 // GenCollectorPolicy methods. | 135 // GenCollectorPolicy methods. |
130 | 136 |
137 size_t GenCollectorPolicy::scale_by_NewRatio_aligned(size_t base_size) { | |
138 size_t x = base_size / (NewRatio+1); | |
139 size_t new_gen_size = x > min_alignment() ? | |
140 align_size_down(x, min_alignment()) : | |
141 min_alignment(); | |
142 return new_gen_size; | |
143 } | |
144 | |
145 size_t GenCollectorPolicy::bound_minus_alignment(size_t desired_size, | |
146 size_t maximum_size) { | |
147 size_t alignment = min_alignment(); | |
148 size_t max_minus = maximum_size - alignment; | |
149 return desired_size < max_minus ? desired_size : max_minus; | |
150 } | |
151 | |
152 | |
131 void GenCollectorPolicy::initialize_size_policy(size_t init_eden_size, | 153 void GenCollectorPolicy::initialize_size_policy(size_t init_eden_size, |
132 size_t init_promo_size, | 154 size_t init_promo_size, |
133 size_t init_survivor_size) { | 155 size_t init_survivor_size) { |
134 double max_gc_minor_pause_sec = ((double) MaxGCMinorPauseMillis)/1000.0; | 156 const double max_gc_minor_pause_sec = ((double) MaxGCMinorPauseMillis)/1000.0; |
135 _size_policy = new AdaptiveSizePolicy(init_eden_size, | 157 _size_policy = new AdaptiveSizePolicy(init_eden_size, |
136 init_promo_size, | 158 init_promo_size, |
137 init_survivor_size, | 159 init_survivor_size, |
138 max_gc_minor_pause_sec, | 160 max_gc_minor_pause_sec, |
139 GCTimeRatio); | 161 GCTimeRatio); |
208 // Check validity of heap flags | 230 // Check validity of heap flags |
209 assert(OldSize % min_alignment() == 0, "old space alignment"); | 231 assert(OldSize % min_alignment() == 0, "old space alignment"); |
210 assert(MaxHeapSize % max_alignment() == 0, "maximum heap alignment"); | 232 assert(MaxHeapSize % max_alignment() == 0, "maximum heap alignment"); |
211 } | 233 } |
212 | 234 |
235 // Values set on the command line win over any ergonomically | |
236 // set command line parameters. | |
237 // Ergonomic choice of parameters are done before this | |
238 // method is called. Values for command line parameters such as NewSize | |
239 // and MaxNewSize feed those ergonomic choices into this method. | |
240 // This method makes the final generation sizings consistent with | |
241 // themselves and with overall heap sizings. | |
242 // In the absence of explicitly set command line flags, policies | |
243 // such as the use of NewRatio are used to size the generation. | |
213 void GenCollectorPolicy::initialize_size_info() { | 244 void GenCollectorPolicy::initialize_size_info() { |
214 CollectorPolicy::initialize_size_info(); | 245 CollectorPolicy::initialize_size_info(); |
215 | 246 |
216 // Minimum sizes of the generations may be different than | 247 // min_alignment() is used for alignment within a generation. |
217 // the initial sizes. | 248 // There is additional alignment done down stream for some |
218 if (!FLAG_IS_DEFAULT(NewSize)) { | 249 // collectors that sometimes causes unwanted rounding up of |
219 _min_gen0_size = NewSize; | 250 // generations sizes. |
251 | |
252 // Determine maximum size of gen0 | |
253 | |
254 size_t max_new_size = 0; | |
255 if (FLAG_IS_CMDLINE(MaxNewSize)) { | |
256 if (MaxNewSize < min_alignment()) { | |
257 max_new_size = min_alignment(); | |
258 } else if (MaxNewSize >= max_heap_byte_size()) { | |
259 max_new_size = align_size_down(max_heap_byte_size() - min_alignment(), | |
260 min_alignment()); | |
261 warning("MaxNewSize (" SIZE_FORMAT "k) is equal to or " | |
262 "greater than the entire heap (" SIZE_FORMAT "k). A " | |
263 "new generation size of " SIZE_FORMAT "k will be used.", | |
264 MaxNewSize/K, max_heap_byte_size()/K, max_new_size/K); | |
265 } else { | |
266 max_new_size = align_size_down(MaxNewSize, min_alignment()); | |
267 } | |
268 | |
269 // The case for FLAG_IS_ERGO(MaxNewSize) could be treated | |
270 // specially at this point to just use an ergonomically set | |
271 // MaxNewSize to set max_new_size. For cases with small | |
272 // heaps such a policy often did not work because the MaxNewSize | |
273 // was larger than the entire heap. The interpretation given | |
274 // to ergonomically set flags is that the flags are set | |
275 // by different collectors for their own special needs but | |
276 // are not allowed to badly shape the heap. This allows the | |
277 // different collectors to decide what's best for themselves | |
278 // without having to factor in the overall heap shape. It | |
279 // can be the case in the future that the collectors would | |
280 // only make "wise" ergonomics choices and this policy could | |
281 // just accept those choices. The choices currently made are | |
282 // not always "wise". | |
220 } else { | 283 } else { |
221 _min_gen0_size = align_size_down(_min_heap_byte_size / (NewRatio+1), | 284 max_new_size = scale_by_NewRatio_aligned(max_heap_byte_size()); |
222 min_alignment()); | 285 // Bound the maximum size by NewSize below (since it historically |
223 // We bound the minimum size by NewSize below (since it historically | |
224 // would have been NewSize and because the NewRatio calculation could | 286 // would have been NewSize and because the NewRatio calculation could |
225 // yield a size that is too small) and bound it by MaxNewSize above. | 287 // yield a size that is too small) and bound it by MaxNewSize above. |
226 // This is not always best. The NewSize calculated by CMS (which has | 288 // Ergonomics plays here by previously calculating the desired |
227 // a fixed minimum of 16m) can sometimes be "too" large. Consider | 289 // NewSize and MaxNewSize. |
228 // the case where -Xmx32m. The CMS calculated NewSize would be about | 290 max_new_size = MIN2(MAX2(max_new_size, NewSize), MaxNewSize); |
229 // half the entire heap which seems too large. But the counter | 291 } |
230 // example is seen when the client defaults for NewRatio are used. | 292 assert(max_new_size > 0, "All paths should set max_new_size"); |
231 // An initial young generation size of 640k was observed | 293 |
232 // with -Xmx128m -XX:MaxNewSize=32m when NewSize was not used | 294 // Given the maximum gen0 size, determine the initial and |
233 // as a lower bound as with | 295 // minimum sizes. |
234 // _min_gen0_size = MIN2(_min_gen0_size, MaxNewSize); | 296 |
235 // and 640k seemed too small a young generation. | 297 if (max_heap_byte_size() == min_heap_byte_size()) { |
236 _min_gen0_size = MIN2(MAX2(_min_gen0_size, NewSize), MaxNewSize); | 298 // The maximum and minimum heap sizes are the same so |
237 } | 299 // the generations minimum and initial must be the |
238 | 300 // same as its maximum. |
239 // Parameters are valid, compute area sizes. | 301 set_min_gen0_size(max_new_size); |
240 size_t max_new_size = align_size_down(_max_heap_byte_size / (NewRatio+1), | 302 set_initial_gen0_size(max_new_size); |
241 min_alignment()); | 303 set_max_gen0_size(max_new_size); |
242 max_new_size = MIN2(MAX2(max_new_size, _min_gen0_size), MaxNewSize); | 304 } else { |
243 | 305 size_t desired_new_size = 0; |
244 // desired_new_size is used to set the initial size. The | 306 if (!FLAG_IS_DEFAULT(NewSize)) { |
245 // initial size must be greater than the minimum size. | 307 // If NewSize is set ergonomically (for example by cms), it |
246 size_t desired_new_size = | 308 // would make sense to use it. If it is used, also use it |
247 align_size_down(_initial_heap_byte_size / (NewRatio+1), | 309 // to set the initial size. Although there is no reason |
248 min_alignment()); | 310 // the minimum size and the initial size have to be the same, |
249 | 311 // the current implementation gets into trouble during the calculation |
250 size_t new_size = MIN2(MAX2(desired_new_size, _min_gen0_size), max_new_size); | 312 // of the tenured generation sizes if they are different. |
251 | 313 // Note that this makes the initial size and the minimum size |
252 _initial_gen0_size = new_size; | 314 // generally small compared to the NewRatio calculation. |
253 _max_gen0_size = max_new_size; | 315 _min_gen0_size = NewSize; |
254 } | 316 desired_new_size = NewSize; |
317 max_new_size = MAX2(max_new_size, NewSize); | |
318 } else { | |
319 // For the case where NewSize is the default, use NewRatio | |
320 // to size the minimum and initial generation sizes. | |
321 // Use the default NewSize as the floor for these values. If | |
322 // NewRatio is overly large, the resulting sizes can be too | |
323 // small. | |
324 _min_gen0_size = MAX2(scale_by_NewRatio_aligned(min_heap_byte_size()), | |
325 NewSize); | |
326 desired_new_size = | |
327 MAX2(scale_by_NewRatio_aligned(initial_heap_byte_size()), | |
328 NewSize); | |
329 } | |
330 | |
331 assert(_min_gen0_size > 0, "Sanity check"); | |
332 set_initial_gen0_size(desired_new_size); | |
333 set_max_gen0_size(max_new_size); | |
334 | |
335 // At this point the desirable initial and minimum sizes have been | |
336 // determined without regard to the maximum sizes. | |
337 | |
338 // Bound the sizes by the corresponding overall heap sizes. | |
339 set_min_gen0_size( | |
340 bound_minus_alignment(_min_gen0_size, min_heap_byte_size())); | |
341 set_initial_gen0_size( | |
342 bound_minus_alignment(_initial_gen0_size, initial_heap_byte_size())); | |
343 set_max_gen0_size( | |
344 bound_minus_alignment(_max_gen0_size, max_heap_byte_size())); | |
345 | |
346 // At this point all three sizes have been checked against the | |
347 // maximum sizes but have not been checked for consistency | |
348 // amoung the three. | |
349 | |
350 // Final check min <= initial <= max | |
351 set_min_gen0_size(MIN2(_min_gen0_size, _max_gen0_size)); | |
352 set_initial_gen0_size( | |
353 MAX2(MIN2(_initial_gen0_size, _max_gen0_size), _min_gen0_size)); | |
354 set_min_gen0_size(MIN2(_min_gen0_size, _initial_gen0_size)); | |
355 } | |
356 | |
357 if (PrintGCDetails && Verbose) { | |
358 gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT " Initial gen0 " | |
359 SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, | |
360 min_gen0_size(), initial_gen0_size(), max_gen0_size()); | |
361 } | |
362 } | |
363 | |
364 // Call this method during the sizing of the gen1 to make | |
365 // adjustments to gen0 because of gen1 sizing policy. gen0 initially has | |
366 // the most freedom in sizing because it is done before the | |
367 // policy for gen1 is applied. Once gen1 policies have been applied, | |
368 // there may be conflicts in the shape of the heap and this method | |
369 // is used to make the needed adjustments. The application of the | |
370 // policies could be more sophisticated (iterative for example) but | |
371 // keeping it simple also seems a worthwhile goal. | |
372 bool TwoGenerationCollectorPolicy::adjust_gen0_sizes(size_t* gen0_size_ptr, | |
373 size_t* gen1_size_ptr, | |
374 size_t heap_size, | |
375 size_t min_gen0_size) { | |
376 bool result = false; | |
377 if ((*gen1_size_ptr + *gen0_size_ptr) > heap_size) { | |
378 if (((*gen0_size_ptr + OldSize) > heap_size) && | |
379 (heap_size - min_gen0_size) >= min_alignment()) { | |
380 // Adjust gen0 down to accomodate OldSize | |
381 *gen0_size_ptr = heap_size - min_gen0_size; | |
382 *gen0_size_ptr = | |
383 MAX2((uintx)align_size_down(*gen0_size_ptr, min_alignment()), | |
384 min_alignment()); | |
385 assert(*gen0_size_ptr > 0, "Min gen0 is too large"); | |
386 result = true; | |
387 } else { | |
388 *gen1_size_ptr = heap_size - *gen0_size_ptr; | |
389 *gen1_size_ptr = | |
390 MAX2((uintx)align_size_down(*gen1_size_ptr, min_alignment()), | |
391 min_alignment()); | |
392 } | |
393 } | |
394 return result; | |
395 } | |
396 | |
397 // Minimum sizes of the generations may be different than | |
398 // the initial sizes. An inconsistently is permitted here | |
399 // in the total size that can be specified explicitly by | |
400 // command line specification of OldSize and NewSize and | |
401 // also a command line specification of -Xms. Issue a warning | |
402 // but allow the values to pass. | |
255 | 403 |
256 void TwoGenerationCollectorPolicy::initialize_size_info() { | 404 void TwoGenerationCollectorPolicy::initialize_size_info() { |
257 GenCollectorPolicy::initialize_size_info(); | 405 GenCollectorPolicy::initialize_size_info(); |
258 | 406 |
259 // Minimum sizes of the generations may be different than | 407 // At this point the minimum, initial and maximum sizes |
260 // the initial sizes. An inconsistently is permitted here | 408 // of the overall heap and of gen0 have been determined. |
261 // in the total size that can be specified explicitly by | 409 // The maximum gen1 size can be determined from the maximum gen0 |
262 // command line specification of OldSize and NewSize and | 410 // and maximum heap size since not explicit flags exits |
263 // also a command line specification of -Xms. Issue a warning | 411 // for setting the gen1 maximum. |
264 // but allow the values to pass. | 412 _max_gen1_size = max_heap_byte_size() - _max_gen0_size; |
265 if (!FLAG_IS_DEFAULT(OldSize)) { | 413 _max_gen1_size = |
266 _min_gen1_size = OldSize; | 414 MAX2((uintx)align_size_down(_max_gen1_size, min_alignment()), |
415 min_alignment()); | |
416 // If no explicit command line flag has been set for the | |
417 // gen1 size, use what is left for gen1. | |
418 if (FLAG_IS_DEFAULT(OldSize) || FLAG_IS_ERGO(OldSize)) { | |
419 // The user has not specified any value or ergonomics | |
420 // has chosen a value (which may or may not be consistent | |
421 // with the overall heap size). In either case make | |
422 // the minimum, maximum and initial sizes consistent | |
423 // with the gen0 sizes and the overall heap sizes. | |
424 assert(min_heap_byte_size() > _min_gen0_size, | |
425 "gen0 has an unexpected minimum size"); | |
426 set_min_gen1_size(min_heap_byte_size() - min_gen0_size()); | |
427 set_min_gen1_size( | |
428 MAX2((uintx)align_size_down(_min_gen1_size, min_alignment()), | |
429 min_alignment())); | |
430 set_initial_gen1_size(initial_heap_byte_size() - initial_gen0_size()); | |
431 set_initial_gen1_size( | |
432 MAX2((uintx)align_size_down(_initial_gen1_size, min_alignment()), | |
433 min_alignment())); | |
434 | |
435 } else { | |
436 // It's been explicitly set on the command line. Use the | |
437 // OldSize and then determine the consequences. | |
438 set_min_gen1_size(OldSize); | |
439 set_initial_gen1_size(OldSize); | |
440 | |
441 // If the user has explicitly set an OldSize that is inconsistent | |
442 // with other command line flags, issue a warning. | |
267 // The generation minimums and the overall heap mimimum should | 443 // The generation minimums and the overall heap mimimum should |
268 // be within one heap alignment. | 444 // be within one heap alignment. |
269 if ((_min_gen1_size + _min_gen0_size + max_alignment()) < | 445 if ((_min_gen1_size + _min_gen0_size + min_alignment()) < |
270 _min_heap_byte_size) { | 446 min_heap_byte_size()) { |
271 warning("Inconsistency between minimum heap size and minimum " | 447 warning("Inconsistency between minimum heap size and minimum " |
272 "generation sizes: using min heap = " SIZE_FORMAT, | 448 "generation sizes: using minimum heap = " SIZE_FORMAT, |
273 _min_heap_byte_size); | 449 min_heap_byte_size()); |
274 } | 450 } |
275 } else { | 451 if ((OldSize > _max_gen1_size)) { |
276 _min_gen1_size = _min_heap_byte_size - _min_gen0_size; | 452 warning("Inconsistency between maximum heap size and maximum " |
277 } | 453 "generation sizes: using maximum heap = " SIZE_FORMAT |
278 | 454 " -XX:OldSize flag is being ignored", |
279 _initial_gen1_size = _initial_heap_byte_size - _initial_gen0_size; | 455 max_heap_byte_size()); |
280 _max_gen1_size = _max_heap_byte_size - _max_gen0_size; | 456 } |
457 // If there is an inconsistency between the OldSize and the minimum and/or | |
458 // initial size of gen0, since OldSize was explicitly set, OldSize wins. | |
459 if (adjust_gen0_sizes(&_min_gen0_size, &_min_gen1_size, | |
460 min_heap_byte_size(), OldSize)) { | |
461 if (PrintGCDetails && Verbose) { | |
462 gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT " Initial gen0 " | |
463 SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, | |
464 min_gen0_size(), initial_gen0_size(), max_gen0_size()); | |
465 } | |
466 } | |
467 // Initial size | |
468 if (adjust_gen0_sizes(&_initial_gen0_size, &_initial_gen1_size, | |
469 initial_heap_byte_size(), OldSize)) { | |
470 if (PrintGCDetails && Verbose) { | |
471 gclog_or_tty->print_cr("Minimum gen0 " SIZE_FORMAT " Initial gen0 " | |
472 SIZE_FORMAT " Maximum gen0 " SIZE_FORMAT, | |
473 min_gen0_size(), initial_gen0_size(), max_gen0_size()); | |
474 } | |
475 } | |
476 } | |
477 // Enforce the maximum gen1 size. | |
478 set_min_gen1_size(MIN2(_min_gen1_size, _max_gen1_size)); | |
479 | |
480 // Check that min gen1 <= initial gen1 <= max gen1 | |
481 set_initial_gen1_size(MAX2(_initial_gen1_size, _min_gen1_size)); | |
482 set_initial_gen1_size(MIN2(_initial_gen1_size, _max_gen1_size)); | |
483 | |
484 if (PrintGCDetails && Verbose) { | |
485 gclog_or_tty->print_cr("Minimum gen1 " SIZE_FORMAT " Initial gen1 " | |
486 SIZE_FORMAT " Maximum gen1 " SIZE_FORMAT, | |
487 min_gen1_size(), initial_gen1_size(), max_gen1_size()); | |
488 } | |
281 } | 489 } |
282 | 490 |
283 HeapWord* GenCollectorPolicy::mem_allocate_work(size_t size, | 491 HeapWord* GenCollectorPolicy::mem_allocate_work(size_t size, |
284 bool is_tlab, | 492 bool is_tlab, |
285 bool* gc_overhead_limit_was_exceeded) { | 493 bool* gc_overhead_limit_was_exceeded) { |