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