提交 aea40d98 编写于 作者: J johnc

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
上级 bdf28cda
...@@ -146,43 +146,6 @@ void CollectionSetChooser::sort_regions() { ...@@ -146,43 +146,6 @@ void CollectionSetChooser::sort_regions() {
verify(); verify();
} }
uint CollectionSetChooser::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) _length;
const size_t gc_num = (size_t) G1MixedGCCountTarget;
size_t result = region_num / gc_num;
// emulate ceiling
if (result * gc_num < region_num) {
result += 1;
}
return (uint) result;
}
uint CollectionSetChooser::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 CollectionSetChooser::add_region(HeapRegion* hr) { void CollectionSetChooser::add_region(HeapRegion* hr) {
assert(!hr->isHumongous(), assert(!hr->isHumongous(),
......
...@@ -51,6 +51,8 @@ class CollectionSetChooser: public CHeapObj<mtGC> { ...@@ -51,6 +51,8 @@ class CollectionSetChooser: public CHeapObj<mtGC> {
uint _curr_index; uint _curr_index;
// The number of candidate old regions added to the CSet chooser. // The number of candidate old regions added to the CSet chooser.
// Note: this is not updated when removing a region using
// remove_and_move_to_next() below.
uint _length; uint _length;
// Keeps track of the start of the next array chunk to be claimed by // Keeps track of the start of the next array chunk to be claimed by
...@@ -111,13 +113,8 @@ public: ...@@ -111,13 +113,8 @@ public:
hr->live_bytes() < _region_live_threshold_bytes; hr->live_bytes() < _region_live_threshold_bytes;
} }
// Calculate the minimum number of old regions we'll add to the CSet // Returns the number candidate old regions added
// during a mixed GC. uint length() { return _length; }
uint calc_min_old_cset_length();
// Calculate the maximum number of old regions we'll add to the CSet
// during a mixed GC.
uint calc_max_old_cset_length();
// Serial version. // Serial version.
void add_region(HeapRegion *hr); void add_region(HeapRegion *hr);
......
...@@ -1806,6 +1806,14 @@ void G1CollectorPolicy::print_collection_set(HeapRegion* list_head, outputStream ...@@ -1806,6 +1806,14 @@ void G1CollectorPolicy::print_collection_set(HeapRegion* list_head, outputStream
} }
#endif // !PRODUCT #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, bool G1CollectorPolicy::next_gc_should_be_mixed(const char* true_action_str,
const char* false_action_str) { const char* false_action_str) {
CollectionSetChooser* cset_chooser = _collectionSetChooser; CollectionSetChooser* cset_chooser = _collectionSetChooser;
...@@ -1815,19 +1823,21 @@ bool G1CollectorPolicy::next_gc_should_be_mixed(const char* true_action_str, ...@@ -1815,19 +1823,21 @@ bool G1CollectorPolicy::next_gc_should_be_mixed(const char* true_action_str,
ergo_format_reason("candidate old regions not available")); ergo_format_reason("candidate old regions not available"));
return false; return false;
} }
// Is the amount of uncollected reclaimable space above G1HeapWastePercent?
size_t reclaimable_bytes = cset_chooser->remaining_reclaimable_bytes(); size_t reclaimable_bytes = cset_chooser->remaining_reclaimable_bytes();
size_t capacity_bytes = _g1->capacity(); double reclaimable_perc = reclaimable_bytes_perc(reclaimable_bytes);
double perc = (double) reclaimable_bytes * 100.0 / (double) capacity_bytes;
double threshold = (double) G1HeapWastePercent; double threshold = (double) G1HeapWastePercent;
if (perc < threshold) { if (reclaimable_perc <= threshold) {
ergo_verbose4(ErgoMixedGCs, ergo_verbose4(ErgoMixedGCs,
false_action_str, 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_region("candidate old regions")
ergo_format_byte_perc("reclaimable") ergo_format_byte_perc("reclaimable")
ergo_format_perc("threshold"), ergo_format_perc("threshold"),
cset_chooser->remaining_regions(), cset_chooser->remaining_regions(),
reclaimable_bytes, perc, threshold); reclaimable_bytes,
reclaimable_perc, threshold);
return false; return false;
} }
...@@ -1838,10 +1848,50 @@ bool G1CollectorPolicy::next_gc_should_be_mixed(const char* true_action_str, ...@@ -1838,10 +1848,50 @@ bool G1CollectorPolicy::next_gc_should_be_mixed(const char* true_action_str,
ergo_format_byte_perc("reclaimable") ergo_format_byte_perc("reclaimable")
ergo_format_perc("threshold"), ergo_format_perc("threshold"),
cset_chooser->remaining_regions(), cset_chooser->remaining_regions(),
reclaimable_bytes, perc, threshold); reclaimable_bytes,
reclaimable_perc, threshold);
return true; 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) { void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
double young_start_time_sec = os::elapsedTime(); double young_start_time_sec = os::elapsedTime();
...@@ -1855,7 +1905,7 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) { ...@@ -1855,7 +1905,7 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
double base_time_ms = predict_base_elapsed_time_ms(_pending_cards); double base_time_ms = predict_base_elapsed_time_ms(_pending_cards);
double predicted_pause_time_ms = base_time_ms; 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, ergo_verbose4(ErgoCSetConstruction | ErgoHigh,
"start choosing CSet", "start choosing CSet",
...@@ -1893,7 +1943,7 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) { ...@@ -1893,7 +1943,7 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
_collection_set = _inc_cset_head; _collection_set = _inc_cset_head;
_collection_set_bytes_used_before = _inc_cset_bytes_used_before; _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; predicted_pause_time_ms += _inc_cset_predicted_elapsed_time_ms;
ergo_verbose3(ErgoCSetConstruction | ErgoHigh, ergo_verbose3(ErgoCSetConstruction | ErgoHigh,
...@@ -1917,8 +1967,8 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) { ...@@ -1917,8 +1967,8 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
if (!gcs_are_young()) { if (!gcs_are_young()) {
CollectionSetChooser* cset_chooser = _collectionSetChooser; CollectionSetChooser* cset_chooser = _collectionSetChooser;
cset_chooser->verify(); cset_chooser->verify();
const uint min_old_cset_length = cset_chooser->calc_min_old_cset_length(); const uint min_old_cset_length = calc_min_old_cset_length();
const uint max_old_cset_length = cset_chooser->calc_max_old_cset_length(); const uint max_old_cset_length = calc_max_old_cset_length();
uint expensive_region_num = 0; uint expensive_region_num = 0;
bool check_time_remaining = adaptive_young_list_length(); bool check_time_remaining = adaptive_young_list_length();
...@@ -1936,6 +1986,30 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) { ...@@ -1936,6 +1986,30 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
break; 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()); double predicted_time_ms = predict_region_elapsed_time_ms(hr, gcs_are_young());
if (check_time_remaining) { if (check_time_remaining) {
if (predicted_time_ms > time_remaining_ms) { if (predicted_time_ms > time_remaining_ms) {
...@@ -1975,7 +2049,7 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) { ...@@ -1975,7 +2049,7 @@ void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
} }
// We will add this region to the CSet. // 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; predicted_pause_time_ms += predicted_time_ms;
cset_chooser->remove_and_move_to_next(hr); cset_chooser->remove_and_move_to_next(hr);
_g1->old_set_remove(hr); _g1->old_set_remove(hr);
......
...@@ -619,6 +619,18 @@ private: ...@@ -619,6 +619,18 @@ private:
bool predict_will_fit(uint young_length, double base_time_ms, bool predict_will_fit(uint young_length, double base_time_ms,
uint base_free_regions, double target_pause_time_ms); uint base_free_regions, double target_pause_time_ms);
// Calculate the minimum number of old regions we'll add to the CSet
// during a mixed GC.
uint calc_min_old_cset_length();
// Calculate the maximum number of old regions we'll add to the CSet
// during a mixed GC.
uint calc_max_old_cset_length();
// Returns the given amount of uncollected reclaimable space
// as a percentage of the current heap capacity.
double reclaimable_bytes_perc(size_t reclaimable_bytes);
public: public:
G1CollectorPolicy(); G1CollectorPolicy();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册