Mercurial > hg > graal-compiler
diff src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @ 8681:27714220e50e
8007036: G1: Too many old regions added to last mixed GC
Summary: Stop adding old regions to collection set when the remaining reclaimable bytes reaches, or goes below, G1HeapWastePercent. Changes were also reviewed by Vitaly Davidovich <vitalyd@gmail.com>.
Reviewed-by: brutisso
author | johnc |
---|---|
date | Mon, 04 Mar 2013 12:42:14 -0800 |
parents | f1fb03a251e9 |
children | cc32ccaaf47f 71013d764f6e |
line wrap: on
line diff
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Mon Mar 04 13:01:24 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Mon Mar 04 12:42:14 2013 -0800 @@ -1806,6 +1806,14 @@ } #endif // !PRODUCT +double G1CollectorPolicy::reclaimable_bytes_perc(size_t reclaimable_bytes) { + // Returns the given amount of reclaimable bytes (that represents + // the amount of reclaimable space still to be collected) as a + // percentage of the current heap capacity. + size_t capacity_bytes = _g1->capacity(); + return (double) reclaimable_bytes * 100.0 / (double) capacity_bytes; +} + bool G1CollectorPolicy::next_gc_should_be_mixed(const char* true_action_str, const char* false_action_str) { CollectionSetChooser* cset_chooser = _collectionSetChooser; @@ -1815,19 +1823,21 @@ ergo_format_reason("candidate old regions not available")); return false; } + + // Is the amount of uncollected reclaimable space above G1HeapWastePercent? size_t reclaimable_bytes = cset_chooser->remaining_reclaimable_bytes(); - size_t capacity_bytes = _g1->capacity(); - double perc = (double) reclaimable_bytes * 100.0 / (double) capacity_bytes; + double reclaimable_perc = reclaimable_bytes_perc(reclaimable_bytes); double threshold = (double) G1HeapWastePercent; - if (perc < threshold) { + if (reclaimable_perc <= threshold) { ergo_verbose4(ErgoMixedGCs, false_action_str, - ergo_format_reason("reclaimable percentage lower than threshold") + ergo_format_reason("reclaimable percentage not over threshold") ergo_format_region("candidate old regions") ergo_format_byte_perc("reclaimable") ergo_format_perc("threshold"), cset_chooser->remaining_regions(), - reclaimable_bytes, perc, threshold); + reclaimable_bytes, + reclaimable_perc, threshold); return false; } @@ -1838,10 +1848,50 @@ ergo_format_byte_perc("reclaimable") ergo_format_perc("threshold"), cset_chooser->remaining_regions(), - reclaimable_bytes, perc, threshold); + reclaimable_bytes, + reclaimable_perc, threshold); return true; } +uint G1CollectorPolicy::calc_min_old_cset_length() { + // The min old CSet region bound is based on the maximum desired + // number of mixed GCs after a cycle. I.e., even if some old regions + // look expensive, we should add them to the CSet anyway to make + // sure we go through the available old regions in no more than the + // maximum desired number of mixed GCs. + // + // The calculation is based on the number of marked regions we added + // to the CSet chooser in the first place, not how many remain, so + // that the result is the same during all mixed GCs that follow a cycle. + + const size_t region_num = (size_t) _collectionSetChooser->length(); + const size_t gc_num = (size_t) MAX2(G1MixedGCCountTarget, (uintx) 1); + size_t result = region_num / gc_num; + // emulate ceiling + if (result * gc_num < region_num) { + result += 1; + } + return (uint) result; +} + +uint G1CollectorPolicy::calc_max_old_cset_length() { + // The max old CSet region bound is based on the threshold expressed + // as a percentage of the heap size. I.e., it should bound the + // number of old regions added to the CSet irrespective of how many + // of them are available. + + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + const size_t region_num = g1h->n_regions(); + const size_t perc = (size_t) G1OldCSetRegionThresholdPercent; + size_t result = region_num * perc / 100; + // emulate ceiling + if (100 * result < region_num * perc) { + result += 1; + } + return (uint) result; +} + + void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) { double young_start_time_sec = os::elapsedTime(); @@ -1855,7 +1905,7 @@ double base_time_ms = predict_base_elapsed_time_ms(_pending_cards); double predicted_pause_time_ms = base_time_ms; - double time_remaining_ms = target_pause_time_ms - base_time_ms; + double time_remaining_ms = MAX2(target_pause_time_ms - base_time_ms, 0.0); ergo_verbose4(ErgoCSetConstruction | ErgoHigh, "start choosing CSet", @@ -1893,7 +1943,7 @@ _collection_set = _inc_cset_head; _collection_set_bytes_used_before = _inc_cset_bytes_used_before; - time_remaining_ms -= _inc_cset_predicted_elapsed_time_ms; + time_remaining_ms = MAX2(time_remaining_ms - _inc_cset_predicted_elapsed_time_ms, 0.0); predicted_pause_time_ms += _inc_cset_predicted_elapsed_time_ms; ergo_verbose3(ErgoCSetConstruction | ErgoHigh, @@ -1917,8 +1967,8 @@ if (!gcs_are_young()) { CollectionSetChooser* cset_chooser = _collectionSetChooser; cset_chooser->verify(); - const uint min_old_cset_length = cset_chooser->calc_min_old_cset_length(); - const uint max_old_cset_length = cset_chooser->calc_max_old_cset_length(); + const uint min_old_cset_length = calc_min_old_cset_length(); + const uint max_old_cset_length = calc_max_old_cset_length(); uint expensive_region_num = 0; bool check_time_remaining = adaptive_young_list_length(); @@ -1936,6 +1986,30 @@ break; } + + // Stop adding regions if the remaining reclaimable space is + // not above G1HeapWastePercent. + size_t reclaimable_bytes = cset_chooser->remaining_reclaimable_bytes(); + double reclaimable_perc = reclaimable_bytes_perc(reclaimable_bytes); + double threshold = (double) G1HeapWastePercent; + if (reclaimable_perc <= threshold) { + // We've added enough old regions that the amount of uncollected + // reclaimable space is at or below the waste threshold. Stop + // adding old regions to the CSet. + ergo_verbose5(ErgoCSetConstruction, + "finish adding old regions to CSet", + ergo_format_reason("reclaimable percentage not over threshold") + ergo_format_region("old") + ergo_format_region("max") + ergo_format_byte_perc("reclaimable") + ergo_format_perc("threshold"), + old_cset_region_length(), + max_old_cset_length, + reclaimable_bytes, + reclaimable_perc, threshold); + break; + } + double predicted_time_ms = predict_region_elapsed_time_ms(hr, gcs_are_young()); if (check_time_remaining) { if (predicted_time_ms > time_remaining_ms) { @@ -1975,7 +2049,7 @@ } // We will add this region to the CSet. - time_remaining_ms -= predicted_time_ms; + time_remaining_ms = MAX2(time_remaining_ms - predicted_time_ms, 0.0); predicted_pause_time_ms += predicted_time_ms; cset_chooser->remove_and_move_to_next(hr); _g1->old_set_remove(hr);