8142935: Adding old gen regions does not consider available free space
Track live data size as added to cset during mixed GCs Reviewed-by: kbarrett, drwhite
This commit is contained in:
parent
fd827daa57
commit
dc360cad53
@ -59,12 +59,14 @@ G1CollectionSet::G1CollectionSet(G1CollectedHeap* g1h) :
|
||||
|
||||
_head(NULL),
|
||||
_bytes_used_before(0),
|
||||
_bytes_live_before(0),
|
||||
_recorded_rs_lengths(0),
|
||||
// Incremental CSet attributes
|
||||
_inc_build_state(Inactive),
|
||||
_inc_head(NULL),
|
||||
_inc_tail(NULL),
|
||||
_inc_bytes_used_before(0),
|
||||
_inc_bytes_live_before(0),
|
||||
_inc_recorded_rs_lengths(0),
|
||||
_inc_recorded_rs_lengths_diffs(0),
|
||||
_inc_predicted_elapsed_time_ms(0.0),
|
||||
@ -95,6 +97,7 @@ void G1CollectionSet::add_old_region(HeapRegion* hr) {
|
||||
hr->set_next_in_collection_set(_head);
|
||||
_head = hr;
|
||||
_bytes_used_before += hr->used();
|
||||
_bytes_live_before += hr->live_bytes();
|
||||
size_t rs_length = hr->rem_set()->occupied();
|
||||
_recorded_rs_lengths += rs_length;
|
||||
_old_region_length += 1;
|
||||
@ -107,6 +110,7 @@ void G1CollectionSet::start_incremental_building() {
|
||||
_inc_head = NULL;
|
||||
_inc_tail = NULL;
|
||||
_inc_bytes_used_before = 0;
|
||||
_inc_bytes_live_before = 0;
|
||||
|
||||
_inc_recorded_rs_lengths = 0;
|
||||
_inc_recorded_rs_lengths_diffs = 0;
|
||||
@ -209,6 +213,7 @@ void G1CollectionSet::add_young_region_common(HeapRegion* hr) {
|
||||
_inc_recorded_rs_lengths += rs_length;
|
||||
_inc_predicted_elapsed_time_ms += region_elapsed_time_ms;
|
||||
_inc_bytes_used_before += used_bytes;
|
||||
_inc_bytes_live_before += hr->live_bytes();
|
||||
|
||||
assert(!hr->in_collection_set(), "invariant");
|
||||
_g1->register_young_region_with_cset(hr);
|
||||
@ -311,6 +316,7 @@ double G1CollectionSet::finalize_young_part(double target_pause_time_ms) {
|
||||
|
||||
_head = _inc_head;
|
||||
_bytes_used_before = _inc_bytes_used_before;
|
||||
_bytes_live_before = _inc_bytes_live_before;
|
||||
time_remaining_ms = MAX2(time_remaining_ms - _inc_predicted_elapsed_time_ms, 0.0);
|
||||
|
||||
log_trace(gc, ergo, cset)("Add young regions to CSet. eden: %u regions, survivors: %u regions, predicted young region time: %1.2fms, target pause time: %1.2fms",
|
||||
@ -334,6 +340,7 @@ void G1CollectionSet::finalize_old_part(double time_remaining_ms) {
|
||||
cset_chooser()->verify();
|
||||
const uint min_old_cset_length = _policy->calc_min_old_cset_length();
|
||||
const uint max_old_cset_length = _policy->calc_max_old_cset_length();
|
||||
const size_t estimated_available_bytes = _policy->available_bytes_estimate();
|
||||
|
||||
uint expensive_region_num = 0;
|
||||
bool check_time_remaining = _policy->adaptive_young_list_length();
|
||||
@ -362,6 +369,13 @@ void G1CollectionSet::finalize_old_part(double time_remaining_ms) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Stop adding regions if the live bytes (according to the last marking)
|
||||
// added so far would exceed the estimated free bytes.
|
||||
if ((_bytes_live_before + hr->live_bytes()) > estimated_available_bytes) {
|
||||
log_debug(gc, ergo, cset)("Finish adding old regions to CSet (reached estimated free space limit)");
|
||||
break;
|
||||
}
|
||||
|
||||
double predicted_time_ms = predict_region_elapsed_time_ms(hr);
|
||||
if (check_time_remaining) {
|
||||
if (predicted_time_ms > time_remaining_ms) {
|
||||
|
@ -57,6 +57,9 @@ class G1CollectionSet VALUE_OBJ_CLASS_SPEC {
|
||||
// (if any) to the collection set.
|
||||
size_t _bytes_used_before;
|
||||
|
||||
// The sum of live bytes in the collection set, set as described above.
|
||||
size_t _bytes_live_before;
|
||||
|
||||
size_t _recorded_rs_lengths;
|
||||
|
||||
// The associated information that is maintained while the incremental
|
||||
@ -81,6 +84,9 @@ class G1CollectionSet VALUE_OBJ_CLASS_SPEC {
|
||||
// an evacuation pause.
|
||||
size_t _inc_bytes_used_before;
|
||||
|
||||
// The number of live bytes in the incrementally built collection set.
|
||||
size_t _inc_bytes_live_before;
|
||||
|
||||
// The RSet lengths recorded for regions in the CSet. It is updated
|
||||
// by the thread that adds a new region to the CSet. We assume that
|
||||
// only one thread can be allocating a new CSet region (currently,
|
||||
@ -173,6 +179,10 @@ public:
|
||||
_bytes_used_before = 0;
|
||||
}
|
||||
|
||||
void reset_bytes_live_before() {
|
||||
_bytes_live_before = 0;
|
||||
}
|
||||
|
||||
// Choose a new collection set. Marks the chosen regions as being
|
||||
// "in_collection_set", and links them together. The head and number of
|
||||
// the collection set are available via access methods.
|
||||
|
@ -221,12 +221,7 @@ bool G1CollectorPolicy::predict_will_fit(uint young_length,
|
||||
// When copying, we will likely need more bytes free than is live in the region.
|
||||
// Add some safety margin to factor in the confidence of our guess, and the
|
||||
// natural expected waste.
|
||||
// (100.0 / G1ConfidencePercent) is a scale factor that expresses the uncertainty
|
||||
// of the calculation: the lower the confidence, the more headroom.
|
||||
// (100 + TargetPLABWastePct) represents the increase in expected bytes during
|
||||
// copying due to anticipated waste in the PLABs.
|
||||
double safety_factor = (100.0 / G1ConfidencePercent) * (100 + TargetPLABWastePct) / 100.0;
|
||||
size_t expected_bytes_to_copy = (size_t)(safety_factor * bytes_to_copy);
|
||||
size_t expected_bytes_to_copy = (size_t)(bytes_to_copy * safety_factor());
|
||||
|
||||
if (expected_bytes_to_copy > free_bytes) {
|
||||
// end condition 3: out-of-space
|
||||
@ -592,6 +587,7 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec) {
|
||||
_pending_cards = _g1->pending_card_num();
|
||||
|
||||
_collection_set->reset_bytes_used_before();
|
||||
_collection_set->reset_bytes_live_before();
|
||||
_bytes_copied_during_gc = 0;
|
||||
|
||||
collector_state()->set_last_gc_was_young(false);
|
||||
@ -1266,6 +1262,15 @@ uint G1CollectorPolicy::calc_max_old_cset_length() const {
|
||||
return (uint) result;
|
||||
}
|
||||
|
||||
size_t G1CollectorPolicy::available_bytes_estimate() {
|
||||
size_t estimated_available_bytes = 0;
|
||||
if (_free_regions_at_end_of_collection > _reserve_regions) {
|
||||
uint available_regions = _free_regions_at_end_of_collection - _reserve_regions;
|
||||
estimated_available_bytes = (size_t)((available_regions * HeapRegion::GrainBytes) / safety_factor());
|
||||
}
|
||||
return estimated_available_bytes;
|
||||
}
|
||||
|
||||
void G1CollectorPolicy::finalize_collection_set(double target_pause_time_ms) {
|
||||
double time_remaining_ms = _collection_set->finalize_young_part(target_pause_time_ms);
|
||||
_collection_set->finalize_old_part(time_remaining_ms);
|
||||
|
@ -169,6 +169,21 @@ public:
|
||||
|
||||
double accum_yg_surv_rate_pred(int age) const;
|
||||
|
||||
// When copying, we will likely need more bytes free than is live in the region.
|
||||
// Add some safety margin to factor in the confidence of our guess, and the
|
||||
// natural expected waste.
|
||||
// (100.0 / G1ConfidencePercent) is a scale factor that expresses the uncertainty
|
||||
// of the calculation: the lower the confidence, the more headroom.
|
||||
// (100 + TargetPLABWastePct) represents the increase in expected bytes during
|
||||
// copying due to anticipated waste in the PLABs.
|
||||
double safety_factor() const {
|
||||
return (100.0 / G1ConfidencePercent) * (100 + TargetPLABWastePct) / 100.0;
|
||||
}
|
||||
|
||||
// Returns an estimate of the available bytes at end of collection, adjusted by
|
||||
// the safety factor.
|
||||
size_t available_bytes_estimate();
|
||||
|
||||
protected:
|
||||
G1CollectionSet* _collection_set;
|
||||
virtual double average_time_ms(G1GCPhaseTimes::GCParPhases phase) const;
|
||||
|
Loading…
Reference in New Issue
Block a user