src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
Print this page
rev 3486 : 7185699: G1: Prediction model discrepancies
Summary: Correct the result value of G1CollectedHeap::pending_card_num(). Change the code that calculates the GC efficiency of a non-young heap region to use historical data from mixed GCs and the actual number of live bytes when predicting how long it would take to collect the region.
Reviewed-by:
*** 801,811 ****
_cur_collection_pause_used_at_start_bytes = start_used;
_cur_collection_pause_used_regions_at_start = _g1->used_regions();
_pending_cards = _g1->pending_card_num();
_max_pending_cards = _g1->max_pending_card_num();
! _bytes_in_collection_set_before_gc = 0;
_bytes_copied_during_gc = 0;
YoungList* young_list = _g1->young_list();
_eden_bytes_before_gc = young_list->eden_used_bytes();
_survivor_bytes_before_gc = young_list->survivor_used_bytes();
--- 801,811 ----
_cur_collection_pause_used_at_start_bytes = start_used;
_cur_collection_pause_used_regions_at_start = _g1->used_regions();
_pending_cards = _g1->pending_card_num();
_max_pending_cards = _g1->max_pending_card_num();
! _collection_set_bytes_used_before = 0;
_bytes_copied_during_gc = 0;
YoungList* young_list = _g1->young_list();
_eden_bytes_before_gc = young_list->eden_used_bytes();
_survivor_bytes_before_gc = young_list->survivor_used_bytes();
*** 1124,1136 ****
double constant_other_time_ms = all_other_time_ms -
(young_other_time_ms + non_young_other_time_ms);
_constant_other_time_ms_seq->add(constant_other_time_ms);
double survival_ratio = 0.0;
! if (_bytes_in_collection_set_before_gc > 0) {
survival_ratio = (double) _bytes_copied_during_gc /
! (double) _bytes_in_collection_set_before_gc;
}
_pending_cards_seq->add((double) _pending_cards);
_rs_lengths_seq->add((double) _max_rs_lengths);
}
--- 1124,1136 ----
double constant_other_time_ms = all_other_time_ms -
(young_other_time_ms + non_young_other_time_ms);
_constant_other_time_ms_seq->add(constant_other_time_ms);
double survival_ratio = 0.0;
! if (_collection_set_bytes_used_before > 0) {
survival_ratio = (double) _bytes_copied_during_gc /
! (double) _collection_set_bytes_used_before;
}
_pending_cards_seq->add((double) _pending_cards);
_rs_lengths_seq->add((double) _max_rs_lengths);
}
*** 1227,1236 ****
--- 1227,1245 ----
}
dcqs.notify_if_necessary();
}
double
+ G1CollectorPolicy::predict_base_elapsed_time_ms(size_t pending_cards,
+ size_t scanned_cards) {
+ return
+ predict_rs_update_time_ms(pending_cards) +
+ predict_rs_scan_time_ms(scanned_cards) +
+ predict_constant_other_time_ms();
+ }
+
+ double
G1CollectorPolicy::predict_base_elapsed_time_ms(size_t pending_cards) {
size_t rs_length = predict_rs_length_diff();
size_t card_num;
if (gcs_are_young()) {
card_num = predict_young_card_num(rs_length);
*** 1238,1254 ****
card_num = predict_non_young_card_num(rs_length);
}
return predict_base_elapsed_time_ms(pending_cards, card_num);
}
! double
! G1CollectorPolicy::predict_base_elapsed_time_ms(size_t pending_cards,
! size_t scanned_cards) {
! return
! predict_rs_update_time_ms(pending_cards) +
! predict_rs_scan_time_ms(scanned_cards) +
! predict_constant_other_time_ms();
}
double
G1CollectorPolicy::predict_region_elapsed_time_ms(HeapRegion* hr,
bool young) {
--- 1247,1267 ----
card_num = predict_non_young_card_num(rs_length);
}
return predict_base_elapsed_time_ms(pending_cards, card_num);
}
! size_t G1CollectorPolicy::predict_bytes_to_copy(HeapRegion* hr) {
! size_t bytes_to_copy;
! if (hr->is_marked())
! bytes_to_copy = hr->max_live_bytes();
! else {
! assert(hr->is_young() && hr->age_in_surv_rate_group() != -1, "invariant");
! int age = hr->age_in_surv_rate_group();
! double yg_surv_rate = predict_yg_surv_rate(age, hr->surv_rate_group());
! bytes_to_copy = (size_t) ((double) hr->used() * yg_surv_rate);
! }
! return bytes_to_copy;
}
double
G1CollectorPolicy::predict_region_elapsed_time_ms(HeapRegion* hr,
bool young) {
*** 1271,1293 ****
region_elapsed_time_ms += predict_non_young_other_time_ms(1);
return region_elapsed_time_ms;
}
- size_t G1CollectorPolicy::predict_bytes_to_copy(HeapRegion* hr) {
- size_t bytes_to_copy;
- if (hr->is_marked())
- bytes_to_copy = hr->max_live_bytes();
- else {
- assert(hr->is_young() && hr->age_in_surv_rate_group() != -1, "invariant");
- int age = hr->age_in_surv_rate_group();
- double yg_surv_rate = predict_yg_surv_rate(age, hr->surv_rate_group());
- bytes_to_copy = (size_t) ((double) hr->used() * yg_surv_rate);
- }
- return bytes_to_copy;
- }
-
void
G1CollectorPolicy::init_cset_region_lengths(uint eden_cset_region_length,
uint survivor_cset_region_length) {
_eden_cset_region_length = eden_cset_region_length;
_survivor_cset_region_length = survivor_cset_region_length;
--- 1284,1293 ----
*** 1340,1365 ****
} else {
return 0;
}
}
- class CountCSClosure: public HeapRegionClosure {
- G1CollectorPolicy* _g1_policy;
- public:
- CountCSClosure(G1CollectorPolicy* g1_policy) :
- _g1_policy(g1_policy) {}
- bool doHeapRegion(HeapRegion* r) {
- _g1_policy->_bytes_in_collection_set_before_gc += r->used();
- return false;
- }
- };
-
- void G1CollectorPolicy::count_CS_bytes_used() {
- CountCSClosure cs_closure(this);
- _g1->collection_set_iterate(&cs_closure);
- }
-
void G1CollectorPolicy::print_tracing_info() const {
_trace_gen0_time_data.print();
_trace_gen1_time_data.print();
}
--- 1340,1349 ----
*** 1852,1863 ****
reclaimable_bytes, perc, threshold);
return true;
}
void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
! // Set this here - in case we're not doing young collections.
! double non_young_start_time_sec = os::elapsedTime();
YoungList* young_list = _g1->young_list();
finalize_incremental_cset_building();
guarantee(target_pause_time_ms > 0.0,
--- 1836,1846 ----
reclaimable_bytes, perc, threshold);
return true;
}
void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
! double young_start_time_sec = os::elapsedTime();
YoungList* young_list = _g1->young_list();
finalize_incremental_cset_building();
guarantee(target_pause_time_ms > 0.0,
*** 1867,1887 ****
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;
! ergo_verbose3(ErgoCSetConstruction | ErgoHigh,
"start choosing CSet",
ergo_format_ms("predicted base time")
ergo_format_ms("remaining time")
ergo_format_ms("target pause time"),
! base_time_ms, time_remaining_ms, target_pause_time_ms);
!
! HeapRegion* hr;
! double young_start_time_sec = os::elapsedTime();
- _collection_set_bytes_used_before = 0;
_last_gc_was_young = gcs_are_young() ? true : false;
if (_last_gc_was_young) {
_trace_gen0_time_data.increment_young_collection_count();
} else {
--- 1850,1867 ----
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;
! ergo_verbose4(ErgoCSetConstruction | ErgoHigh,
"start choosing CSet",
+ ergo_format_size("_pending_cards")
ergo_format_ms("predicted base time")
ergo_format_ms("remaining time")
ergo_format_ms("target pause time"),
! _pending_cards, base_time_ms, time_remaining_ms, target_pause_time_ms);
_last_gc_was_young = gcs_are_young() ? true : false;
if (_last_gc_was_young) {
_trace_gen0_time_data.increment_young_collection_count();
} else {
*** 1893,1903 ****
// [Newly Young Regions ++ Survivors from last pause].
uint survivor_region_length = young_list->survivor_length();
uint eden_region_length = young_list->length() - survivor_region_length;
init_cset_region_lengths(eden_region_length, survivor_region_length);
! hr = young_list->first_survivor_region();
while (hr != NULL) {
assert(hr->is_survivor(), "badly formed young list");
hr->set_young();
hr = hr->get_next_young_region();
}
--- 1873,1884 ----
// [Newly Young Regions ++ Survivors from last pause].
uint survivor_region_length = young_list->survivor_length();
uint eden_region_length = young_list->length() - survivor_region_length;
init_cset_region_lengths(eden_region_length, survivor_region_length);
!
! HeapRegion* hr = young_list->first_survivor_region();
while (hr != NULL) {
assert(hr->is_survivor(), "badly formed young list");
hr->set_young();
hr = hr->get_next_young_region();
}
*** 1924,1944 ****
double young_end_time_sec = os::elapsedTime();
phase_times()->_recorded_young_cset_choice_time_ms =
(young_end_time_sec - young_start_time_sec) * 1000.0;
! // We are doing young collections so reset this.
! non_young_start_time_sec = young_end_time_sec;
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();
uint expensive_region_num = 0;
bool check_time_remaining = adaptive_young_list_length();
HeapRegion* hr = cset_chooser->peek();
while (hr != NULL) {
if (old_cset_region_length() >= max_old_cset_length) {
// Added maximum number of old regions to the CSet.
ergo_verbose2(ErgoCSetConstruction,
--- 1905,1926 ----
double young_end_time_sec = os::elapsedTime();
phase_times()->_recorded_young_cset_choice_time_ms =
(young_end_time_sec - young_start_time_sec) * 1000.0;
! // Set the start of the non-young choice time.
! double non_young_start_time_sec = young_end_time_sec;
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();
uint expensive_region_num = 0;
bool check_time_remaining = adaptive_young_list_length();
+
HeapRegion* hr = cset_chooser->peek();
while (hr != NULL) {
if (old_cset_region_length() >= max_old_cset_length) {
// Added maximum number of old regions to the CSet.
ergo_verbose2(ErgoCSetConstruction,
*** 2023,2034 ****
cset_chooser->verify();
}
stop_incremental_cset_building();
- count_CS_bytes_used();
-
ergo_verbose5(ErgoCSetConstruction,
"finish choosing CSet",
ergo_format_region("eden")
ergo_format_region("survivors")
ergo_format_region("old")
--- 2005,2014 ----