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

changeset 4681
27714220e50e
parent 4650
f1fb03a251e9
child 4889
cc32ccaaf47f
child 4929
71013d764f6e
     1.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Mon Mar 04 13:01:24 2013 +0100
     1.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp	Mon Mar 04 12:42:14 2013 -0800
     1.3 @@ -1806,6 +1806,14 @@
     1.4  }
     1.5  #endif // !PRODUCT
     1.6  
     1.7 +double G1CollectorPolicy::reclaimable_bytes_perc(size_t reclaimable_bytes) {
     1.8 +  // Returns the given amount of reclaimable bytes (that represents
     1.9 +  // the amount of reclaimable space still to be collected) as a
    1.10 +  // percentage of the current heap capacity.
    1.11 +  size_t capacity_bytes = _g1->capacity();
    1.12 +  return (double) reclaimable_bytes * 100.0 / (double) capacity_bytes;
    1.13 +}
    1.14 +
    1.15  bool G1CollectorPolicy::next_gc_should_be_mixed(const char* true_action_str,
    1.16                                                  const char* false_action_str) {
    1.17    CollectionSetChooser* cset_chooser = _collectionSetChooser;
    1.18 @@ -1815,19 +1823,21 @@
    1.19                    ergo_format_reason("candidate old regions not available"));
    1.20      return false;
    1.21    }
    1.22 +
    1.23 +  // Is the amount of uncollected reclaimable space above G1HeapWastePercent?
    1.24    size_t reclaimable_bytes = cset_chooser->remaining_reclaimable_bytes();
    1.25 -  size_t capacity_bytes = _g1->capacity();
    1.26 -  double perc = (double) reclaimable_bytes * 100.0 / (double) capacity_bytes;
    1.27 +  double reclaimable_perc = reclaimable_bytes_perc(reclaimable_bytes);
    1.28    double threshold = (double) G1HeapWastePercent;
    1.29 -  if (perc < threshold) {
    1.30 +  if (reclaimable_perc <= threshold) {
    1.31      ergo_verbose4(ErgoMixedGCs,
    1.32                false_action_str,
    1.33 -              ergo_format_reason("reclaimable percentage lower than threshold")
    1.34 +              ergo_format_reason("reclaimable percentage not over threshold")
    1.35                ergo_format_region("candidate old regions")
    1.36                ergo_format_byte_perc("reclaimable")
    1.37                ergo_format_perc("threshold"),
    1.38                cset_chooser->remaining_regions(),
    1.39 -              reclaimable_bytes, perc, threshold);
    1.40 +              reclaimable_bytes,
    1.41 +              reclaimable_perc, threshold);
    1.42      return false;
    1.43    }
    1.44  
    1.45 @@ -1838,10 +1848,50 @@
    1.46                  ergo_format_byte_perc("reclaimable")
    1.47                  ergo_format_perc("threshold"),
    1.48                  cset_chooser->remaining_regions(),
    1.49 -                reclaimable_bytes, perc, threshold);
    1.50 +                reclaimable_bytes,
    1.51 +                reclaimable_perc, threshold);
    1.52    return true;
    1.53  }
    1.54  
    1.55 +uint G1CollectorPolicy::calc_min_old_cset_length() {
    1.56 +  // The min old CSet region bound is based on the maximum desired
    1.57 +  // number of mixed GCs after a cycle. I.e., even if some old regions
    1.58 +  // look expensive, we should add them to the CSet anyway to make
    1.59 +  // sure we go through the available old regions in no more than the
    1.60 +  // maximum desired number of mixed GCs.
    1.61 +  //
    1.62 +  // The calculation is based on the number of marked regions we added
    1.63 +  // to the CSet chooser in the first place, not how many remain, so
    1.64 +  // that the result is the same during all mixed GCs that follow a cycle.
    1.65 +
    1.66 +  const size_t region_num = (size_t) _collectionSetChooser->length();
    1.67 +  const size_t gc_num = (size_t) MAX2(G1MixedGCCountTarget, (uintx) 1);
    1.68 +  size_t result = region_num / gc_num;
    1.69 +  // emulate ceiling
    1.70 +  if (result * gc_num < region_num) {
    1.71 +    result += 1;
    1.72 +  }
    1.73 +  return (uint) result;
    1.74 +}
    1.75 +
    1.76 +uint G1CollectorPolicy::calc_max_old_cset_length() {
    1.77 +  // The max old CSet region bound is based on the threshold expressed
    1.78 +  // as a percentage of the heap size. I.e., it should bound the
    1.79 +  // number of old regions added to the CSet irrespective of how many
    1.80 +  // of them are available.
    1.81 +
    1.82 +  G1CollectedHeap* g1h = G1CollectedHeap::heap();
    1.83 +  const size_t region_num = g1h->n_regions();
    1.84 +  const size_t perc = (size_t) G1OldCSetRegionThresholdPercent;
    1.85 +  size_t result = region_num * perc / 100;
    1.86 +  // emulate ceiling
    1.87 +  if (100 * result < region_num * perc) {
    1.88 +    result += 1;
    1.89 +  }
    1.90 +  return (uint) result;
    1.91 +}
    1.92 +
    1.93 +
    1.94  void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
    1.95    double young_start_time_sec = os::elapsedTime();
    1.96  
    1.97 @@ -1855,7 +1905,7 @@
    1.98  
    1.99    double base_time_ms = predict_base_elapsed_time_ms(_pending_cards);
   1.100    double predicted_pause_time_ms = base_time_ms;
   1.101 -  double time_remaining_ms = target_pause_time_ms - base_time_ms;
   1.102 +  double time_remaining_ms = MAX2(target_pause_time_ms - base_time_ms, 0.0);
   1.103  
   1.104    ergo_verbose4(ErgoCSetConstruction | ErgoHigh,
   1.105                  "start choosing CSet",
   1.106 @@ -1893,7 +1943,7 @@
   1.107  
   1.108    _collection_set = _inc_cset_head;
   1.109    _collection_set_bytes_used_before = _inc_cset_bytes_used_before;
   1.110 -  time_remaining_ms -= _inc_cset_predicted_elapsed_time_ms;
   1.111 +  time_remaining_ms = MAX2(time_remaining_ms - _inc_cset_predicted_elapsed_time_ms, 0.0);
   1.112    predicted_pause_time_ms += _inc_cset_predicted_elapsed_time_ms;
   1.113  
   1.114    ergo_verbose3(ErgoCSetConstruction | ErgoHigh,
   1.115 @@ -1917,8 +1967,8 @@
   1.116    if (!gcs_are_young()) {
   1.117      CollectionSetChooser* cset_chooser = _collectionSetChooser;
   1.118      cset_chooser->verify();
   1.119 -    const uint min_old_cset_length = cset_chooser->calc_min_old_cset_length();
   1.120 -    const uint max_old_cset_length = cset_chooser->calc_max_old_cset_length();
   1.121 +    const uint min_old_cset_length = calc_min_old_cset_length();
   1.122 +    const uint max_old_cset_length = calc_max_old_cset_length();
   1.123  
   1.124      uint expensive_region_num = 0;
   1.125      bool check_time_remaining = adaptive_young_list_length();
   1.126 @@ -1936,6 +1986,30 @@
   1.127          break;
   1.128        }
   1.129  
   1.130 +
   1.131 +      // Stop adding regions if the remaining reclaimable space is
   1.132 +      // not above G1HeapWastePercent.
   1.133 +      size_t reclaimable_bytes = cset_chooser->remaining_reclaimable_bytes();
   1.134 +      double reclaimable_perc = reclaimable_bytes_perc(reclaimable_bytes);
   1.135 +      double threshold = (double) G1HeapWastePercent;
   1.136 +      if (reclaimable_perc <= threshold) {
   1.137 +        // We've added enough old regions that the amount of uncollected
   1.138 +        // reclaimable space is at or below the waste threshold. Stop
   1.139 +        // adding old regions to the CSet.
   1.140 +        ergo_verbose5(ErgoCSetConstruction,
   1.141 +                      "finish adding old regions to CSet",
   1.142 +                      ergo_format_reason("reclaimable percentage not over threshold")
   1.143 +                      ergo_format_region("old")
   1.144 +                      ergo_format_region("max")
   1.145 +                      ergo_format_byte_perc("reclaimable")
   1.146 +                      ergo_format_perc("threshold"),
   1.147 +                      old_cset_region_length(),
   1.148 +                      max_old_cset_length,
   1.149 +                      reclaimable_bytes,
   1.150 +                      reclaimable_perc, threshold);
   1.151 +        break;
   1.152 +      }
   1.153 +
   1.154        double predicted_time_ms = predict_region_elapsed_time_ms(hr, gcs_are_young());
   1.155        if (check_time_remaining) {
   1.156          if (predicted_time_ms > time_remaining_ms) {
   1.157 @@ -1975,7 +2049,7 @@
   1.158        }
   1.159  
   1.160        // We will add this region to the CSet.
   1.161 -      time_remaining_ms -= predicted_time_ms;
   1.162 +      time_remaining_ms = MAX2(time_remaining_ms - predicted_time_ms, 0.0);
   1.163        predicted_pause_time_ms += predicted_time_ms;
   1.164        cset_chooser->remove_and_move_to_next(hr);
   1.165        _g1->old_set_remove(hr);

mercurial