Mercurial > hg > truffle
comparison src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @ 4729:1cbe7978b021
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
author | brutisso |
---|---|
date | Wed, 21 Dec 2011 22:13:31 +0100 |
parents | 441e946dc1af |
children | 2ace1c4ee8da |
comparison
equal
deleted
inserted
replaced
4728:441e946dc1af | 4729:1cbe7978b021 |
---|---|
134 _recent_gc_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), | 134 _recent_gc_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), |
135 _all_pause_times_ms(new NumberSeq()), | 135 _all_pause_times_ms(new NumberSeq()), |
136 _stop_world_start(0.0), | 136 _stop_world_start(0.0), |
137 _all_stop_world_times_ms(new NumberSeq()), | 137 _all_stop_world_times_ms(new NumberSeq()), |
138 _all_yield_times_ms(new NumberSeq()), | 138 _all_yield_times_ms(new NumberSeq()), |
139 _using_new_ratio_calculations(false), | |
140 | 139 |
141 _summary(new Summary()), | 140 _summary(new Summary()), |
142 | 141 |
143 _cur_clear_ct_time_ms(0.0), | 142 _cur_clear_ct_time_ms(0.0), |
144 _mark_closure_time_ms(0.0), | 143 _mark_closure_time_ms(0.0), |
407 // for the first time during initialization. | 406 // for the first time during initialization. |
408 _reserve_regions = 0; | 407 _reserve_regions = 0; |
409 | 408 |
410 initialize_all(); | 409 initialize_all(); |
411 _collectionSetChooser = new CollectionSetChooser(); | 410 _collectionSetChooser = new CollectionSetChooser(); |
412 } | 411 _young_gen_sizer = new G1YoungGenSizer(); // Must be after call to initialize_flags |
413 | |
414 // Increment "i", mod "len" | |
415 static void inc_mod(int& i, int len) { | |
416 i++; if (i == len) i = 0; | |
417 } | 412 } |
418 | 413 |
419 void G1CollectorPolicy::initialize_flags() { | 414 void G1CollectorPolicy::initialize_flags() { |
420 set_min_alignment(HeapRegion::GrainBytes); | 415 set_min_alignment(HeapRegion::GrainBytes); |
421 set_max_alignment(GenRemSet::max_alignment_constraint(rem_set_name())); | 416 set_max_alignment(GenRemSet::max_alignment_constraint(rem_set_name())); |
423 vm_exit_during_initialization("Invalid survivor ratio specified"); | 418 vm_exit_during_initialization("Invalid survivor ratio specified"); |
424 } | 419 } |
425 CollectorPolicy::initialize_flags(); | 420 CollectorPolicy::initialize_flags(); |
426 } | 421 } |
427 | 422 |
428 // The easiest way to deal with the parsing of the NewSize / | 423 G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true) { |
429 // MaxNewSize / etc. parameteres is to re-use the code in the | 424 assert(G1DefaultMinNewGenPercent <= G1DefaultMaxNewGenPercent, "Min larger than max"); |
430 // TwoGenerationCollectorPolicy class. This is similar to what | 425 assert(G1DefaultMinNewGenPercent > 0 && G1DefaultMinNewGenPercent < 100, "Min out of bounds"); |
431 // ParallelScavenge does with its GenerationSizer class (see | 426 assert(G1DefaultMaxNewGenPercent > 0 && G1DefaultMaxNewGenPercent < 100, "Max out of bounds"); |
432 // ParallelScavengeHeap::initialize()). We might change this in the | |
433 // future, but it's a good start. | |
434 class G1YoungGenSizer : public TwoGenerationCollectorPolicy { | |
435 private: | |
436 size_t size_to_region_num(size_t byte_size) { | |
437 return MAX2((size_t) 1, byte_size / HeapRegion::GrainBytes); | |
438 } | |
439 | |
440 public: | |
441 G1YoungGenSizer() { | |
442 initialize_flags(); | |
443 initialize_size_info(); | |
444 } | |
445 size_t min_young_region_num() { | |
446 return size_to_region_num(_min_gen0_size); | |
447 } | |
448 size_t initial_young_region_num() { | |
449 return size_to_region_num(_initial_gen0_size); | |
450 } | |
451 size_t max_young_region_num() { | |
452 return size_to_region_num(_max_gen0_size); | |
453 } | |
454 }; | |
455 | |
456 void G1CollectorPolicy::update_young_list_size_using_newratio(size_t number_of_heap_regions) { | |
457 assert(number_of_heap_regions > 0, "Heap must be initialized"); | |
458 size_t young_size = number_of_heap_regions / (NewRatio + 1); | |
459 _min_desired_young_length = young_size; | |
460 _max_desired_young_length = young_size; | |
461 } | |
462 | |
463 void G1CollectorPolicy::init() { | |
464 // Set aside an initial future to_space. | |
465 _g1 = G1CollectedHeap::heap(); | |
466 | |
467 assert(Heap_lock->owned_by_self(), "Locking discipline."); | |
468 | |
469 initialize_gc_policy_counters(); | |
470 | |
471 G1YoungGenSizer sizer; | |
472 _min_desired_young_length = sizer.min_young_region_num(); | |
473 _max_desired_young_length = sizer.max_young_region_num(); | |
474 | 427 |
475 if (FLAG_IS_CMDLINE(NewRatio)) { | 428 if (FLAG_IS_CMDLINE(NewRatio)) { |
476 if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) { | 429 if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) { |
477 warning("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio"); | 430 warning("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio"); |
478 } else { | 431 } else { |
479 // Treat NewRatio as a fixed size that is only recalculated when the heap size changes | 432 _sizer_kind = SizerNewRatio; |
480 update_young_list_size_using_newratio(_g1->n_regions()); | 433 _adaptive_size = false; |
481 _using_new_ratio_calculations = true; | 434 return; |
482 } | 435 } |
436 } | |
437 | |
438 if (FLAG_IS_CMDLINE(NewSize)) { | |
439 _min_desired_young_length = MAX2((size_t) 1, NewSize / HeapRegion::GrainBytes); | |
440 if (FLAG_IS_CMDLINE(MaxNewSize)) { | |
441 _max_desired_young_length = MAX2((size_t) 1, MaxNewSize / HeapRegion::GrainBytes); | |
442 _sizer_kind = SizerMaxAndNewSize; | |
443 _adaptive_size = _min_desired_young_length == _max_desired_young_length; | |
444 } else { | |
445 _sizer_kind = SizerNewSizeOnly; | |
446 } | |
447 } else if (FLAG_IS_CMDLINE(MaxNewSize)) { | |
448 _max_desired_young_length = MAX2((size_t) 1, MaxNewSize / HeapRegion::GrainBytes); | |
449 _sizer_kind = SizerMaxNewSizeOnly; | |
450 } | |
451 } | |
452 | |
453 size_t G1YoungGenSizer::calculate_default_min_length(size_t new_number_of_heap_regions) { | |
454 size_t default_value = (new_number_of_heap_regions * G1DefaultMinNewGenPercent) / 100; | |
455 return MAX2((size_t)1, default_value); | |
456 } | |
457 | |
458 size_t G1YoungGenSizer::calculate_default_max_length(size_t new_number_of_heap_regions) { | |
459 size_t default_value = (new_number_of_heap_regions * G1DefaultMaxNewGenPercent) / 100; | |
460 return MAX2((size_t)1, default_value); | |
461 } | |
462 | |
463 void G1YoungGenSizer::heap_size_changed(size_t new_number_of_heap_regions) { | |
464 assert(new_number_of_heap_regions > 0, "Heap must be initialized"); | |
465 | |
466 switch (_sizer_kind) { | |
467 case SizerDefaults: | |
468 _min_desired_young_length = calculate_default_min_length(new_number_of_heap_regions); | |
469 _max_desired_young_length = calculate_default_max_length(new_number_of_heap_regions); | |
470 break; | |
471 case SizerNewSizeOnly: | |
472 _max_desired_young_length = calculate_default_max_length(new_number_of_heap_regions); | |
473 _max_desired_young_length = MAX2(_min_desired_young_length, _max_desired_young_length); | |
474 break; | |
475 case SizerMaxNewSizeOnly: | |
476 _min_desired_young_length = calculate_default_min_length(new_number_of_heap_regions); | |
477 _min_desired_young_length = MIN2(_min_desired_young_length, _max_desired_young_length); | |
478 break; | |
479 case SizerMaxAndNewSize: | |
480 // Do nothing. Values set on the command line, don't update them at runtime. | |
481 break; | |
482 case SizerNewRatio: | |
483 _min_desired_young_length = new_number_of_heap_regions / (NewRatio + 1); | |
484 _max_desired_young_length = _min_desired_young_length; | |
485 break; | |
486 default: | |
487 ShouldNotReachHere(); | |
483 } | 488 } |
484 | 489 |
485 assert(_min_desired_young_length <= _max_desired_young_length, "Invalid min/max young gen size values"); | 490 assert(_min_desired_young_length <= _max_desired_young_length, "Invalid min/max young gen size values"); |
486 | 491 } |
487 set_adaptive_young_list_length(_min_desired_young_length < _max_desired_young_length); | 492 |
493 void G1CollectorPolicy::init() { | |
494 // Set aside an initial future to_space. | |
495 _g1 = G1CollectedHeap::heap(); | |
496 | |
497 assert(Heap_lock->owned_by_self(), "Locking discipline."); | |
498 | |
499 initialize_gc_policy_counters(); | |
500 | |
488 if (adaptive_young_list_length()) { | 501 if (adaptive_young_list_length()) { |
489 _young_list_fixed_length = 0; | 502 _young_list_fixed_length = 0; |
490 } else { | 503 } else { |
491 assert(_min_desired_young_length == _max_desired_young_length, "Min and max young size differ"); | 504 _young_list_fixed_length = _young_gen_sizer->min_desired_young_length(); |
492 _young_list_fixed_length = _min_desired_young_length; | |
493 } | 505 } |
494 _free_regions_at_end_of_collection = _g1->free_regions(); | 506 _free_regions_at_end_of_collection = _g1->free_regions(); |
495 update_young_list_target_length(); | 507 update_young_list_target_length(); |
496 _prev_eden_capacity = _young_list_target_length * HeapRegion::GrainBytes; | 508 _prev_eden_capacity = _young_list_target_length * HeapRegion::GrainBytes; |
497 | 509 |
541 double reserve_regions_d = (double) new_number_of_regions * _reserve_factor; | 553 double reserve_regions_d = (double) new_number_of_regions * _reserve_factor; |
542 // We use ceiling so that if reserve_regions_d is > 0.0 (but | 554 // We use ceiling so that if reserve_regions_d is > 0.0 (but |
543 // smaller than 1.0) we'll get 1. | 555 // smaller than 1.0) we'll get 1. |
544 _reserve_regions = (size_t) ceil(reserve_regions_d); | 556 _reserve_regions = (size_t) ceil(reserve_regions_d); |
545 | 557 |
546 if (_using_new_ratio_calculations) { | 558 _young_gen_sizer->heap_size_changed(new_number_of_regions); |
547 // -XX:NewRatio was specified so we need to update the | |
548 // young gen length when the heap size has changed. | |
549 update_young_list_size_using_newratio(new_number_of_regions); | |
550 } | |
551 } | 559 } |
552 | 560 |
553 size_t G1CollectorPolicy::calculate_young_list_desired_min_length( | 561 size_t G1CollectorPolicy::calculate_young_list_desired_min_length( |
554 size_t base_min_length) { | 562 size_t base_min_length) { |
555 size_t desired_min_length = 0; | 563 size_t desired_min_length = 0; |
563 // otherwise we don't have enough info to make the prediction | 571 // otherwise we don't have enough info to make the prediction |
564 } | 572 } |
565 } | 573 } |
566 desired_min_length += base_min_length; | 574 desired_min_length += base_min_length; |
567 // make sure we don't go below any user-defined minimum bound | 575 // make sure we don't go below any user-defined minimum bound |
568 return MAX2(_min_desired_young_length, desired_min_length); | 576 return MAX2(_young_gen_sizer->min_desired_young_length(), desired_min_length); |
569 } | 577 } |
570 | 578 |
571 size_t G1CollectorPolicy::calculate_young_list_desired_max_length() { | 579 size_t G1CollectorPolicy::calculate_young_list_desired_max_length() { |
572 // Here, we might want to also take into account any additional | 580 // Here, we might want to also take into account any additional |
573 // constraints (i.e., user-defined minimum bound). Currently, we | 581 // constraints (i.e., user-defined minimum bound). Currently, we |
574 // effectively don't set this bound. | 582 // effectively don't set this bound. |
575 return _max_desired_young_length; | 583 return _young_gen_sizer->max_desired_young_length(); |
576 } | 584 } |
577 | 585 |
578 void G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) { | 586 void G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) { |
579 if (rs_lengths == (size_t) -1) { | 587 if (rs_lengths == (size_t) -1) { |
580 // if it's set to the default value (-1), we should predict it; | 588 // if it's set to the default value (-1), we should predict it; |