< prev index next >

src/hotspot/share/gc/g1/g1Policy.cpp

Print this page
rev 54086 : imported patch 8219100-cleanup-young-collection-prologue
rev 54087 : imported patch 8218668-reorganize-collection-set


 642       clear_collection_set_candidates();
 643       maybe_start_marking();
 644     }
 645   }
 646 
 647   _short_lived_surv_rate_group->start_adding_regions();
 648   // Do that for any other surv rate groups
 649 
 650   double scan_hcc_time_ms = G1HotCardCache::default_use_cache() ? average_time_ms(G1GCPhaseTimes::ScanHCC) : 0.0;
 651 
 652   if (update_stats) {
 653     double cost_per_card_ms = 0.0;
 654     if (_pending_cards > 0) {
 655       cost_per_card_ms = (average_time_ms(G1GCPhaseTimes::UpdateRS)) / (double) _pending_cards;
 656       _analytics->report_cost_per_card_ms(cost_per_card_ms);
 657     }
 658     _analytics->report_cost_scan_hcc(scan_hcc_time_ms);
 659 
 660     double cost_per_entry_ms = 0.0;
 661     if (cards_scanned > 10) {
 662       cost_per_entry_ms = average_time_ms(G1GCPhaseTimes::ScanRS) / (double) cards_scanned;
 663       _analytics->report_cost_per_entry_ms(cost_per_entry_ms, this_pause_was_young_only);
 664     }
 665 
 666     if (_max_rs_lengths > 0) {
 667       double cards_per_entry_ratio =
 668         (double) cards_scanned / (double) _max_rs_lengths;
 669       _analytics->report_cards_per_entry_ratio(cards_per_entry_ratio, this_pause_was_young_only);
 670     }
 671 
 672     // This is defensive. For a while _max_rs_lengths could get
 673     // smaller than _recorded_rs_lengths which was causing
 674     // rs_length_diff to get very large and mess up the RSet length
 675     // predictions. The reason was unsafe concurrent updates to the
 676     // _inc_cset_recorded_rs_lengths field which the code below guards
 677     // against (see CR 7118202). This bug has now been fixed (see CR
 678     // 7119027). However, I'm still worried that
 679     // _inc_cset_recorded_rs_lengths might still end up somewhat
 680     // inaccurate. The concurrent refinement thread calculates an
 681     // RSet's length concurrently with other CR threads updating it
 682     // which might cause it to calculate the length incorrectly (if,
 683     // say, it's in mid-coarsening). So I'll leave in the defensive
 684     // conditional below just in case.
 685     size_t rs_length_diff = 0;
 686     size_t recorded_rs_lengths = _collection_set->recorded_rs_lengths();
 687     if (_max_rs_lengths > recorded_rs_lengths) {
 688       rs_length_diff = _max_rs_lengths - recorded_rs_lengths;
 689     }
 690     _analytics->report_rs_length_diff((double) rs_length_diff);
 691 
 692     size_t freed_bytes = heap_used_bytes_before_gc - cur_used_bytes;
 693     size_t copied_bytes = _collection_set->bytes_used_before() - freed_bytes;
 694     double cost_per_byte_ms = 0.0;
 695 
 696     if (copied_bytes > 0) {
 697       cost_per_byte_ms = average_time_ms(G1GCPhaseTimes::ObjCopy) / (double) copied_bytes;
 698       _analytics->report_cost_per_byte_ms(cost_per_byte_ms, collector_state()->mark_or_rebuild_in_progress());
 699     }
 700 
 701     if (_collection_set->young_region_length() > 0) {
 702       _analytics->report_young_other_cost_per_region_ms(young_other_time_ms() /
 703                                                         _collection_set->young_region_length());
 704     }
 705 
 706     if (_collection_set->old_region_length() > 0) {
 707       _analytics->report_non_young_other_cost_per_region_ms(non_young_other_time_ms() /
 708                                                             _collection_set->old_region_length());
 709     }
 710 
 711     _analytics->report_constant_other_time_ms(constant_other_time_ms(pause_time_ms));
 712 
 713     // Do not update RS lengths and the number of pending cards with information from mixed gc:
 714     // these are is wildly different to during young only gc and mess up young gen sizing right
 715     // after the mixed gc phase.
 716     // During mixed gc we do not use them for young gen sizing.
 717     if (this_pause_was_young_only) {


1171   return (uint) result;
1172 }
1173 
1174 uint G1Policy::calc_max_old_cset_length() const {
1175   // The max old CSet region bound is based on the threshold expressed
1176   // as a percentage of the heap size. I.e., it should bound the
1177   // number of old regions added to the CSet irrespective of how many
1178   // of them are available.
1179 
1180   const G1CollectedHeap* g1h = G1CollectedHeap::heap();
1181   const size_t region_num = g1h->num_regions();
1182   const size_t perc = (size_t) G1OldCSetRegionThresholdPercent;
1183   size_t result = region_num * perc / 100;
1184   // emulate ceiling
1185   if (100 * result < region_num * perc) {
1186     result += 1;
1187   }
1188   return (uint) result;
1189 }
1190 
1191 uint G1Policy::finalize_collection_set(double target_pause_time_ms, G1SurvivorRegions* survivor) {
1192   double time_remaining_ms = _collection_set->finalize_young_part(target_pause_time_ms, survivor);
1193   _collection_set->finalize_old_part(time_remaining_ms);




























































































































1194 
1195   return _collection_set->region_length();

1196 }
1197 
1198 void G1Policy::transfer_survivors_to_cset(const G1SurvivorRegions* survivors) {
1199 
1200   // Add survivor regions to SurvRateGroup.
1201   note_start_adding_survivor_regions();
1202   finished_recalculating_age_indexes(true /* is_survivors */);
1203 
1204   HeapRegion* last = NULL;
1205   for (GrowableArrayIterator<HeapRegion*> it = survivors->regions()->begin();
1206        it != survivors->regions()->end();
1207        ++it) {
1208     HeapRegion* curr = *it;
1209     set_region_survivor(curr);
1210 
1211     // The region is a non-empty survivor so let's add it to
1212     // the incremental collection set for the next evacuation
1213     // pause.
1214     _collection_set->add_survivor_regions(curr);
1215 


 642       clear_collection_set_candidates();
 643       maybe_start_marking();
 644     }
 645   }
 646 
 647   _short_lived_surv_rate_group->start_adding_regions();
 648   // Do that for any other surv rate groups
 649 
 650   double scan_hcc_time_ms = G1HotCardCache::default_use_cache() ? average_time_ms(G1GCPhaseTimes::ScanHCC) : 0.0;
 651 
 652   if (update_stats) {
 653     double cost_per_card_ms = 0.0;
 654     if (_pending_cards > 0) {
 655       cost_per_card_ms = (average_time_ms(G1GCPhaseTimes::UpdateRS)) / (double) _pending_cards;
 656       _analytics->report_cost_per_card_ms(cost_per_card_ms);
 657     }
 658     _analytics->report_cost_scan_hcc(scan_hcc_time_ms);
 659 
 660     double cost_per_entry_ms = 0.0;
 661     if (cards_scanned > 10) {
 662       cost_per_entry_ms = (average_time_ms(G1GCPhaseTimes::ScanRS) + average_time_ms(G1GCPhaseTimes::OptScanRS)) / (double) cards_scanned;
 663       _analytics->report_cost_per_entry_ms(cost_per_entry_ms, this_pause_was_young_only);
 664     }
 665 
 666     if (_max_rs_lengths > 0) {
 667       double cards_per_entry_ratio =
 668         (double) cards_scanned / (double) _max_rs_lengths;
 669       _analytics->report_cards_per_entry_ratio(cards_per_entry_ratio, this_pause_was_young_only);
 670     }
 671 
 672     // This is defensive. For a while _max_rs_lengths could get
 673     // smaller than _recorded_rs_lengths which was causing
 674     // rs_length_diff to get very large and mess up the RSet length
 675     // predictions. The reason was unsafe concurrent updates to the
 676     // _inc_cset_recorded_rs_lengths field which the code below guards
 677     // against (see CR 7118202). This bug has now been fixed (see CR
 678     // 7119027). However, I'm still worried that
 679     // _inc_cset_recorded_rs_lengths might still end up somewhat
 680     // inaccurate. The concurrent refinement thread calculates an
 681     // RSet's length concurrently with other CR threads updating it
 682     // which might cause it to calculate the length incorrectly (if,
 683     // say, it's in mid-coarsening). So I'll leave in the defensive
 684     // conditional below just in case.
 685     size_t rs_length_diff = 0;
 686     size_t recorded_rs_lengths = _collection_set->recorded_rs_lengths();
 687     if (_max_rs_lengths > recorded_rs_lengths) {
 688       rs_length_diff = _max_rs_lengths - recorded_rs_lengths;
 689     }
 690     _analytics->report_rs_length_diff((double) rs_length_diff);
 691 
 692     size_t freed_bytes = heap_used_bytes_before_gc - cur_used_bytes;
 693     size_t copied_bytes = _collection_set->bytes_used_before() - freed_bytes;
 694     double cost_per_byte_ms = 0.0;
 695 
 696     if (copied_bytes > 0) {
 697       cost_per_byte_ms = (average_time_ms(G1GCPhaseTimes::ObjCopy) + average_time_ms(G1GCPhaseTimes::OptObjCopy)) / (double) copied_bytes;
 698       _analytics->report_cost_per_byte_ms(cost_per_byte_ms, collector_state()->mark_or_rebuild_in_progress());
 699     }
 700 
 701     if (_collection_set->young_region_length() > 0) {
 702       _analytics->report_young_other_cost_per_region_ms(young_other_time_ms() /
 703                                                         _collection_set->young_region_length());
 704     }
 705 
 706     if (_collection_set->old_region_length() > 0) {
 707       _analytics->report_non_young_other_cost_per_region_ms(non_young_other_time_ms() /
 708                                                             _collection_set->old_region_length());
 709     }
 710 
 711     _analytics->report_constant_other_time_ms(constant_other_time_ms(pause_time_ms));
 712 
 713     // Do not update RS lengths and the number of pending cards with information from mixed gc:
 714     // these are is wildly different to during young only gc and mess up young gen sizing right
 715     // after the mixed gc phase.
 716     // During mixed gc we do not use them for young gen sizing.
 717     if (this_pause_was_young_only) {


1171   return (uint) result;
1172 }
1173 
1174 uint G1Policy::calc_max_old_cset_length() const {
1175   // The max old CSet region bound is based on the threshold expressed
1176   // as a percentage of the heap size. I.e., it should bound the
1177   // number of old regions added to the CSet irrespective of how many
1178   // of them are available.
1179 
1180   const G1CollectedHeap* g1h = G1CollectedHeap::heap();
1181   const size_t region_num = g1h->num_regions();
1182   const size_t perc = (size_t) G1OldCSetRegionThresholdPercent;
1183   size_t result = region_num * perc / 100;
1184   // emulate ceiling
1185   if (100 * result < region_num * perc) {
1186     result += 1;
1187   }
1188   return (uint) result;
1189 }
1190 
1191 void G1Policy::select_old_collection_set_regions(G1CollectionSetCandidates* candidates,
1192                                                  double time_remaining_ms,
1193                                                  uint& num_expensive_regions,
1194                                                  uint& num_initial_regions,
1195                                                  uint& num_optional_regions) {
1196   assert(candidates != NULL, "Must be");
1197 
1198   num_initial_regions = 0;
1199   num_optional_regions = 0;
1200   num_expensive_regions = 0;
1201 
1202   double predicted_old_time_ms = 0.0;
1203   double predicted_initial_time_ms = 0.0;
1204   double predicted_optional_time_ms = 0.0;
1205 
1206   double optional_threshold_ms = time_remaining_ms * optional_prediction_fraction();
1207 
1208   const uint min_old_cset_length = calc_min_old_cset_length();
1209   const uint max_old_cset_length = MAX2(min_old_cset_length, calc_max_old_cset_length());
1210   const uint max_optional_regions = max_old_cset_length - min_old_cset_length;
1211   bool check_time_remaining = adaptive_young_list_length();
1212 
1213   uint candidate_idx = candidates->cur_idx();
1214 
1215   log_debug(gc, ergo, cset)("Start adding old regions to collection set. Min %u regions, max %u regions, "
1216                             "time remaining %1.2fms, optional threshold %1.2fms",
1217                             min_old_cset_length, max_old_cset_length, time_remaining_ms, optional_threshold_ms);
1218 
1219   HeapRegion* hr = candidates->at(candidate_idx);
1220   while (hr != NULL) {
1221     if (num_initial_regions + num_optional_regions >= max_old_cset_length) {
1222       // Added maximum number of old regions to the CSet.
1223       log_debug(gc, ergo, cset)("Finish adding old regions to collection set (Maximum number of regions). "
1224                                 "Initial %u regions, optional %u regions",
1225                                 num_initial_regions, num_optional_regions);
1226       break;
1227     }
1228 
1229     // Stop adding regions if the remaining reclaimable space is
1230     // not above G1HeapWastePercent.
1231     size_t reclaimable_bytes = candidates->remaining_reclaimable_bytes();
1232     double reclaimable_percent = reclaimable_bytes_percent(reclaimable_bytes);
1233     double threshold = (double) G1HeapWastePercent;
1234     if (reclaimable_percent <= threshold) {
1235       // We've added enough old regions that the amount of uncollected
1236       // reclaimable space is at or below the waste threshold. Stop
1237       // adding old regions to the CSet.
1238       log_debug(gc, ergo, cset)("Finish adding old regions to collection set (Reclaimable percentage below threshold). "
1239                                 "Reclaimable: " SIZE_FORMAT "%s (%1.2f%%) threshold: " UINTX_FORMAT "%%",
1240                                 byte_size_in_proper_unit(reclaimable_bytes), proper_unit_for_byte_size(reclaimable_bytes),
1241                                 reclaimable_percent, G1HeapWastePercent);
1242       break;
1243     }
1244 
1245     double predicted_time_ms = predict_region_elapsed_time_ms(hr, false);
1246     time_remaining_ms = MAX2(time_remaining_ms - predicted_time_ms, 0.0);
1247     // Add regions to old set until we reach the minimum amount
1248     if (num_initial_regions < min_old_cset_length) {
1249       predicted_old_time_ms += predicted_time_ms;
1250       num_initial_regions++;
1251       // Record the number of regions added with no time remaining
1252       if (time_remaining_ms == 0.0) {
1253         num_expensive_regions++;
1254       }
1255     } else if (!check_time_remaining) {
1256       // In the non-auto-tuning case, we'll finish adding regions
1257       // to the CSet if we reach the minimum.
1258       log_debug(gc, ergo, cset)("Finish adding old regions to collection set (Region amount reached min).");
1259       break;
1260     } else {
1261       // Keep adding regions to old set until we reach the optional threshold
1262       if (time_remaining_ms > optional_threshold_ms) {
1263         predicted_old_time_ms += predicted_time_ms;
1264         num_initial_regions++;
1265       } else if (time_remaining_ms > 0) {
1266         // Keep adding optional regions until time is up.
1267         assert(num_optional_regions < max_optional_regions, "Should not be possible.");
1268         predicted_optional_time_ms += predicted_time_ms;
1269         num_optional_regions++;
1270       } else {
1271         log_debug(gc, ergo, cset)("Finish adding old regions to collection set (Predicted time too high).");
1272         break;
1273       }
1274     }
1275     hr = candidates->at(++candidate_idx);
1276   }
1277   if (hr == NULL) {
1278     log_debug(gc, ergo, cset)("Old candidate collection set empty.");
1279   }
1280 
1281   if (num_expensive_regions > 0) {
1282     log_debug(gc, ergo, cset)("Added %u initial old regions to collection set although the predicted time was too high.",
1283                               num_expensive_regions);
1284   }
1285 
1286   log_debug(gc, ergo, cset)("Finish choosing collection set old regions. Initial: %u, optional: %u, "
1287                             "predicted old time: %1.2fms, predicted optional time: %1.2fms, time remaining: %1.2f",
1288                             num_initial_regions, num_optional_regions,
1289                             predicted_initial_time_ms, predicted_optional_time_ms, time_remaining_ms);
1290 }
1291 
1292 void G1Policy::select_optional_collection_set_regions(G1CollectionSetCandidates* candidates,
1293                                                       uint const max_optional_regions,
1294                                                       double time_remaining_ms,
1295                                                       uint& num_optional_regions) {
1296   assert(_g1h->collector_state()->in_mixed_phase(), "Should only be called in mixed phase");
1297 
1298   num_optional_regions = 0;
1299   double prediction_ms = 0;
1300   uint candidate_idx = candidates->cur_idx();
1301 
1302   HeapRegion* r = candidates->at(candidate_idx);
1303   while (num_optional_regions < max_optional_regions) {
1304     assert(r != NULL, "Region must exist");
1305     prediction_ms += predict_region_elapsed_time_ms(r, false);
1306 
1307     if (prediction_ms > time_remaining_ms) {
1308       log_debug(gc, ergo, cset)("Prediction %.3fms for region %u does not fit remaining time: %.3fms.",
1309                                 prediction_ms, r->hrm_index(), time_remaining_ms);
1310       break;
1311     }
1312     // This region will be included in the next optional evacuation.
1313 
1314     time_remaining_ms -= prediction_ms;
1315     num_optional_regions++;
1316     r = candidates->at(++candidate_idx);
1317   }
1318 
1319   log_debug(gc, ergo, cset)("Prepared %u regions out of %u for optional evacuation. Predicted time: %.3fms",
1320                             num_optional_regions, max_optional_regions, prediction_ms);
1321 }
1322 
1323 void G1Policy::transfer_survivors_to_cset(const G1SurvivorRegions* survivors) {
1324 
1325   // Add survivor regions to SurvRateGroup.
1326   note_start_adding_survivor_regions();
1327   finished_recalculating_age_indexes(true /* is_survivors */);
1328 
1329   HeapRegion* last = NULL;
1330   for (GrowableArrayIterator<HeapRegion*> it = survivors->regions()->begin();
1331        it != survivors->regions()->end();
1332        ++it) {
1333     HeapRegion* curr = *it;
1334     set_region_survivor(curr);
1335 
1336     // The region is a non-empty survivor so let's add it to
1337     // the incremental collection set for the next evacuation
1338     // pause.
1339     _collection_set->add_survivor_regions(curr);
1340 
< prev index next >