src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp

Print this page
rev 2895 : 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


 119 
 120   void append_and_print_cr(const char* format, ...) {
 121     va_list ap;
 122     va_start(ap, format);
 123     vappend(format, ap);
 124     va_end(ap);
 125     gclog_or_tty->print_cr("%s", _buffer);
 126     _cur = _indent_level * INDENT_CHARS;
 127   }
 128 };
 129 
 130 G1CollectorPolicy::G1CollectorPolicy() :
 131   _parallel_gc_threads(G1CollectedHeap::use_parallel_gc_threads()
 132                         ? ParallelGCThreads : 1),
 133 
 134   _recent_gc_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
 135   _all_pause_times_ms(new NumberSeq()),
 136   _stop_world_start(0.0),
 137   _all_stop_world_times_ms(new NumberSeq()),
 138   _all_yield_times_ms(new NumberSeq()),
 139   _using_new_ratio_calculations(false),
 140 
 141   _summary(new Summary()),
 142 
 143   _cur_clear_ct_time_ms(0.0),
 144   _mark_closure_time_ms(0.0),
 145 
 146   _cur_ref_proc_time_ms(0.0),
 147   _cur_ref_enq_time_ms(0.0),
 148 
 149 #ifndef PRODUCT
 150   _min_clear_cc_time_ms(-1.0),
 151   _max_clear_cc_time_ms(-1.0),
 152   _cur_clear_cc_time_ms(0.0),
 153   _cum_clear_cc_time_ms(0.0),
 154   _num_cc_clears(0L),
 155 #endif
 156 
 157   _aux_num(10),
 158   _all_aux_times_ms(new NumberSeq[_aux_num]),
 159   _cur_aux_start_times_ms(new double[_aux_num]),


 390 
 391   assert(GCTimeRatio > 0,
 392          "we should have set it to a default value set_g1_gc_flags() "
 393          "if a user set it to 0");
 394   _gc_overhead_perc = 100.0 * (1.0 / (1.0 + GCTimeRatio));
 395 
 396   uintx reserve_perc = G1ReservePercent;
 397   // Put an artificial ceiling on this so that it's not set to a silly value.
 398   if (reserve_perc > 50) {
 399     reserve_perc = 50;
 400     warning("G1ReservePercent is set to a value that is too large, "
 401             "it's been updated to %u", reserve_perc);
 402   }
 403   _reserve_factor = (double) reserve_perc / 100.0;
 404   // This will be set when the heap is expanded
 405   // for the first time during initialization.
 406   _reserve_regions = 0;
 407 
 408   initialize_all();
 409   _collectionSetChooser = new CollectionSetChooser();
 410 }
 411 
 412 // Increment "i", mod "len"
 413 static void inc_mod(int& i, int len) {
 414   i++; if (i == len) i = 0;
 415 }
 416 
 417 void G1CollectorPolicy::initialize_flags() {
 418   set_min_alignment(HeapRegion::GrainBytes);
 419   set_max_alignment(GenRemSet::max_alignment_constraint(rem_set_name()));
 420   if (SurvivorRatio < 1) {
 421     vm_exit_during_initialization("Invalid survivor ratio specified");
 422   }
 423   CollectorPolicy::initialize_flags();
 424 }
 425 
 426 // The easiest way to deal with the parsing of the NewSize /
 427 // MaxNewSize / etc. parameteres is to re-use the code in the
 428 // TwoGenerationCollectorPolicy class. This is similar to what
 429 // ParallelScavenge does with its GenerationSizer class (see
 430 // ParallelScavengeHeap::initialize()). We might change this in the
 431 // future, but it's a good start.
 432 class G1YoungGenSizer : public TwoGenerationCollectorPolicy {
 433 private:
 434   size_t size_to_region_num(size_t byte_size) {
 435     return MAX2((size_t) 1, byte_size / HeapRegion::GrainBytes);
 436   }
 437 
 438 public:
 439   G1YoungGenSizer() {
 440     initialize_flags();
 441     initialize_size_info();
 442   }
 443   size_t min_young_region_num() {
 444     return size_to_region_num(_min_gen0_size);
 445   }
 446   size_t initial_young_region_num() {
 447     return size_to_region_num(_initial_gen0_size);
 448   }
 449   size_t max_young_region_num() {
 450     return size_to_region_num(_max_gen0_size);
 451   }
 452 };
 453 
 454 void G1CollectorPolicy::update_young_list_size_using_newratio(size_t number_of_heap_regions) {
 455   assert(number_of_heap_regions > 0, "Heap must be initialized");
 456   size_t young_size = number_of_heap_regions / (NewRatio + 1);
 457   _min_desired_young_length = young_size;
 458   _max_desired_young_length = young_size;
 459 }
 460 
 461 void G1CollectorPolicy::init() {
 462   // Set aside an initial future to_space.
 463   _g1 = G1CollectedHeap::heap();
 464 
 465   assert(Heap_lock->owned_by_self(), "Locking discipline.");


 466 
 467   initialize_gc_policy_counters();


 468 
 469   G1YoungGenSizer sizer;
 470   _min_desired_young_length = sizer.min_young_region_num();
 471   _max_desired_young_length = sizer.max_young_region_num();
 472 
 473   if (FLAG_IS_CMDLINE(NewRatio)) {
 474     if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) {
 475       warning("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio");
 476     } else {
 477       // Treat NewRatio as a fixed size that is only recalculated when the heap size changes
 478       update_young_list_size_using_newratio(_g1->n_regions());
 479       _using_new_ratio_calculations = true;
 480     }

















 481   }
 482 
 483   assert(_min_desired_young_length <= _max_desired_young_length, "Invalid min/max young gen size values");









 484 
 485   set_adaptive_young_list_length(_min_desired_young_length < _max_desired_young_length);
 486   if (adaptive_young_list_length()) {
 487     _young_list_fixed_length = 0;
 488   } else {
 489     assert(_min_desired_young_length == _max_desired_young_length, "Min and max young size differ");
 490     _young_list_fixed_length = _min_desired_young_length;
 491   }
 492   _free_regions_at_end_of_collection = _g1->free_regions();
 493   update_young_list_target_length();
 494   _prev_eden_capacity = _young_list_target_length * HeapRegion::GrainBytes;
 495 
 496   // We may immediately start allocating regions and placing them on the
 497   // collection set list. Initialize the per-collection set info
 498   start_incremental_cset_building();
 499 }
 500 
 501 // Create the jstat counters for the policy.
 502 void G1CollectorPolicy::initialize_gc_policy_counters() {
 503   _gc_policy_counters = new GCPolicyCounters("GarbageFirst", 1, 3);
 504 }
 505 
 506 bool G1CollectorPolicy::predict_will_fit(size_t young_length,
 507                                          double base_time_ms,
 508                                          size_t base_free_regions,
 509                                          double target_pause_time_ms) {
 510   if (young_length >= base_free_regions) {


 524   }
 525 
 526   size_t free_bytes =
 527                   (base_free_regions - young_length) * HeapRegion::GrainBytes;
 528   if ((2.0 * sigma()) * (double) bytes_to_copy > (double) free_bytes) {
 529     // end condition 3: out-of-space (conservatively!)
 530     return false;
 531   }
 532 
 533   // success!
 534   return true;
 535 }
 536 
 537 void G1CollectorPolicy::record_new_heap_size(size_t new_number_of_regions) {
 538   // re-calculate the necessary reserve
 539   double reserve_regions_d = (double) new_number_of_regions * _reserve_factor;
 540   // We use ceiling so that if reserve_regions_d is > 0.0 (but
 541   // smaller than 1.0) we'll get 1.
 542   _reserve_regions = (size_t) ceil(reserve_regions_d);
 543 
 544   if (_using_new_ratio_calculations) {
 545     // -XX:NewRatio was specified so we need to update the
 546     // young gen length when the heap size has changed.
 547     update_young_list_size_using_newratio(new_number_of_regions);
 548   }
 549 }
 550 
 551 size_t G1CollectorPolicy::calculate_young_list_desired_min_length(
 552                                                      size_t base_min_length) {
 553   size_t desired_min_length = 0;
 554   if (adaptive_young_list_length()) {
 555     if (_alloc_rate_ms_seq->num() > 3) {
 556       double now_sec = os::elapsedTime();
 557       double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0;
 558       double alloc_rate_ms = predict_alloc_rate_ms();
 559       desired_min_length = (size_t) ceil(alloc_rate_ms * when_ms);
 560     } else {
 561       // otherwise we don't have enough info to make the prediction
 562     }
 563   }
 564   desired_min_length += base_min_length;
 565   // make sure we don't go below any user-defined minimum bound
 566   return MAX2(_min_desired_young_length, desired_min_length);
 567 }
 568 
 569 size_t G1CollectorPolicy::calculate_young_list_desired_max_length() {
 570   // Here, we might want to also take into account any additional
 571   // constraints (i.e., user-defined minimum bound). Currently, we
 572   // effectively don't set this bound.
 573   return _max_desired_young_length;
 574 }
 575 
 576 void G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) {
 577   if (rs_lengths == (size_t) -1) {
 578     // if it's set to the default value (-1), we should predict it;
 579     // otherwise, use the given value.
 580     rs_lengths = (size_t) get_new_prediction(_rs_lengths_seq);
 581   }
 582 
 583   // Calculate the absolute and desired min bounds.
 584 
 585   // This is how many young regions we already have (currently: the survivors).
 586   size_t base_min_length = recorded_survivor_regions();
 587   // This is the absolute minimum young length, which ensures that we
 588   // can allocate one eden region in the worst-case.
 589   size_t absolute_min_length = base_min_length + 1;
 590   size_t desired_min_length =
 591                      calculate_young_list_desired_min_length(base_min_length);
 592   if (desired_min_length < absolute_min_length) {
 593     desired_min_length = absolute_min_length;




 119 
 120   void append_and_print_cr(const char* format, ...) {
 121     va_list ap;
 122     va_start(ap, format);
 123     vappend(format, ap);
 124     va_end(ap);
 125     gclog_or_tty->print_cr("%s", _buffer);
 126     _cur = _indent_level * INDENT_CHARS;
 127   }
 128 };
 129 
 130 G1CollectorPolicy::G1CollectorPolicy() :
 131   _parallel_gc_threads(G1CollectedHeap::use_parallel_gc_threads()
 132                         ? ParallelGCThreads : 1),
 133 
 134   _recent_gc_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)),
 135   _all_pause_times_ms(new NumberSeq()),
 136   _stop_world_start(0.0),
 137   _all_stop_world_times_ms(new NumberSeq()),
 138   _all_yield_times_ms(new NumberSeq()),

 139 
 140   _summary(new Summary()),
 141 
 142   _cur_clear_ct_time_ms(0.0),
 143   _mark_closure_time_ms(0.0),
 144 
 145   _cur_ref_proc_time_ms(0.0),
 146   _cur_ref_enq_time_ms(0.0),
 147 
 148 #ifndef PRODUCT
 149   _min_clear_cc_time_ms(-1.0),
 150   _max_clear_cc_time_ms(-1.0),
 151   _cur_clear_cc_time_ms(0.0),
 152   _cum_clear_cc_time_ms(0.0),
 153   _num_cc_clears(0L),
 154 #endif
 155 
 156   _aux_num(10),
 157   _all_aux_times_ms(new NumberSeq[_aux_num]),
 158   _cur_aux_start_times_ms(new double[_aux_num]),


 389 
 390   assert(GCTimeRatio > 0,
 391          "we should have set it to a default value set_g1_gc_flags() "
 392          "if a user set it to 0");
 393   _gc_overhead_perc = 100.0 * (1.0 / (1.0 + GCTimeRatio));
 394 
 395   uintx reserve_perc = G1ReservePercent;
 396   // Put an artificial ceiling on this so that it's not set to a silly value.
 397   if (reserve_perc > 50) {
 398     reserve_perc = 50;
 399     warning("G1ReservePercent is set to a value that is too large, "
 400             "it's been updated to %u", reserve_perc);
 401   }
 402   _reserve_factor = (double) reserve_perc / 100.0;
 403   // This will be set when the heap is expanded
 404   // for the first time during initialization.
 405   _reserve_regions = 0;
 406 
 407   initialize_all();
 408   _collectionSetChooser = new CollectionSetChooser();
 409   _young_gen_sizer = new G1YoungGenSizer(); // Must be after call to initialize_flags




 410 }
 411 
 412 void G1CollectorPolicy::initialize_flags() {
 413   set_min_alignment(HeapRegion::GrainBytes);
 414   set_max_alignment(GenRemSet::max_alignment_constraint(rem_set_name()));
 415   if (SurvivorRatio < 1) {
 416     vm_exit_during_initialization("Invalid survivor ratio specified");
 417   }
 418   CollectorPolicy::initialize_flags();
 419 }
 420 
 421 G1YoungGenSizer::G1YoungGenSizer() : _sizer_kind(SizerDefaults), _adaptive_size(true) {
 422   if (FLAG_IS_CMDLINE(NewRatio)) {
 423     if (FLAG_IS_CMDLINE(NewSize) || FLAG_IS_CMDLINE(MaxNewSize)) {
 424       warning("-XX:NewSize and -XX:MaxNewSize override -XX:NewRatio");
 425     } else {
 426       _sizer_kind = SizerNewRatio;
 427       _adaptive_size = false;
 428       return;
 429     }
 430   }
 431 
 432   if (FLAG_IS_CMDLINE(NewSize)) {
 433      _min_desired_young_length = MAX2((size_t) 1, NewSize / HeapRegion::GrainBytes);
 434     if (FLAG_IS_CMDLINE(MaxNewSize)) {
 435       _max_desired_young_length = MAX2((size_t) 1, MaxNewSize / HeapRegion::GrainBytes);
 436       _sizer_kind = SizerMaxAndNewSize;
 437       _adaptive_size = _min_desired_young_length == _max_desired_young_length;
 438     } else {
 439       _sizer_kind = SizerNewSizeOnly;
 440     }
 441   } else if (FLAG_IS_CMDLINE(MaxNewSize)) {
 442     _max_desired_young_length = MAX2((size_t) 1, MaxNewSize / HeapRegion::GrainBytes);
 443     _sizer_kind = SizerMaxNewSizeOnly;
 444   }









 445 }
 446 
 447 size_t G1YoungGenSizer::calculate_default_min_size(size_t new_number_of_heap_regions) {
 448   assert(G1DefaultMinNewGenPercent <= G1DefaultMaxNewGenPercent, "Min larger than max");
 449   assert(G1DefaultMinNewGenPercent > 0 && G1DefaultMinNewGenPercent < 100, "Min out of bounds");
 450 
 451   size_t default_value = (new_number_of_heap_regions * G1DefaultMinNewGenPercent) / 100;
 452   return MAX2((size_t)1, default_value);
 453 }
 454 
 455 size_t G1YoungGenSizer::calculate_default_max_size(size_t new_number_of_heap_regions) {
 456   assert(G1DefaultMinNewGenPercent <= G1DefaultMaxNewGenPercent, "Min larger than max");
 457   assert(G1DefaultMaxNewGenPercent > 0 && G1DefaultMaxNewGenPercent < 100, "Max out of bounds");
 458 
 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_size(new_number_of_heap_regions);
 469       _max_desired_young_length = calculate_default_max_size(new_number_of_heap_regions);
 470       break;
 471     case SizerNewSizeOnly:
 472       _max_desired_young_length = calculate_default_max_size(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_size(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();
 488   }
 489 
 490   assert(_min_desired_young_length <= _max_desired_young_length, "Invalid min/max young gen size values");
 491 }
 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 

 501   if (adaptive_young_list_length()) {
 502     _young_list_fixed_length = 0;
 503   } else {
 504     _young_list_fixed_length = _young_gen_sizer->min_desired_young_length();

 505   }
 506   _free_regions_at_end_of_collection = _g1->free_regions();
 507   update_young_list_target_length();
 508   _prev_eden_capacity = _young_list_target_length * HeapRegion::GrainBytes;
 509 
 510   // We may immediately start allocating regions and placing them on the
 511   // collection set list. Initialize the per-collection set info
 512   start_incremental_cset_building();
 513 }
 514 
 515 // Create the jstat counters for the policy.
 516 void G1CollectorPolicy::initialize_gc_policy_counters() {
 517   _gc_policy_counters = new GCPolicyCounters("GarbageFirst", 1, 3);
 518 }
 519 
 520 bool G1CollectorPolicy::predict_will_fit(size_t young_length,
 521                                          double base_time_ms,
 522                                          size_t base_free_regions,
 523                                          double target_pause_time_ms) {
 524   if (young_length >= base_free_regions) {


 538   }
 539 
 540   size_t free_bytes =
 541                   (base_free_regions - young_length) * HeapRegion::GrainBytes;
 542   if ((2.0 * sigma()) * (double) bytes_to_copy > (double) free_bytes) {
 543     // end condition 3: out-of-space (conservatively!)
 544     return false;
 545   }
 546 
 547   // success!
 548   return true;
 549 }
 550 
 551 void G1CollectorPolicy::record_new_heap_size(size_t new_number_of_regions) {
 552   // re-calculate the necessary reserve
 553   double reserve_regions_d = (double) new_number_of_regions * _reserve_factor;
 554   // We use ceiling so that if reserve_regions_d is > 0.0 (but
 555   // smaller than 1.0) we'll get 1.
 556   _reserve_regions = (size_t) ceil(reserve_regions_d);
 557 
 558   _young_gen_sizer->heap_size_changed(new_number_of_regions);




 559 }
 560 
 561 size_t G1CollectorPolicy::calculate_young_list_desired_min_length(
 562                                                      size_t base_min_length) {
 563   size_t desired_min_length = 0;
 564   if (adaptive_young_list_length()) {
 565     if (_alloc_rate_ms_seq->num() > 3) {
 566       double now_sec = os::elapsedTime();
 567       double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0;
 568       double alloc_rate_ms = predict_alloc_rate_ms();
 569       desired_min_length = (size_t) ceil(alloc_rate_ms * when_ms);
 570     } else {
 571       // otherwise we don't have enough info to make the prediction
 572     }
 573   }
 574   desired_min_length += base_min_length;
 575   // make sure we don't go below any user-defined minimum bound
 576   return MAX2(_young_gen_sizer->min_desired_young_length(), desired_min_length);
 577 }
 578 
 579 size_t G1CollectorPolicy::calculate_young_list_desired_max_length() {
 580   // Here, we might want to also take into account any additional
 581   // constraints (i.e., user-defined minimum bound). Currently, we
 582   // effectively don't set this bound.
 583   return _young_gen_sizer->max_desired_young_length();
 584 }
 585 
 586 void G1CollectorPolicy::update_young_list_target_length(size_t rs_lengths) {
 587   if (rs_lengths == (size_t) -1) {
 588     // if it's set to the default value (-1), we should predict it;
 589     // otherwise, use the given value.
 590     rs_lengths = (size_t) get_new_prediction(_rs_lengths_seq);
 591   }
 592 
 593   // Calculate the absolute and desired min bounds.
 594 
 595   // This is how many young regions we already have (currently: the survivors).
 596   size_t base_min_length = recorded_survivor_regions();
 597   // This is the absolute minimum young length, which ensures that we
 598   // can allocate one eden region in the worst-case.
 599   size_t absolute_min_length = base_min_length + 1;
 600   size_t desired_min_length =
 601                      calculate_young_list_desired_min_length(base_min_length);
 602   if (desired_min_length < absolute_min_length) {
 603     desired_min_length = absolute_min_length;