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);