comparison src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @ 4912:a9647476d1a4

7132029: G1: mixed GC phase lasts for longer than it should Summary: Revamp of the mechanism that chooses old regions for inclusion in the CSet. It simplifies the code and introduces min and max bounds on the number of old regions added to the CSet at each mixed GC to avoid pathological cases. It also ensures that when we do a mixed GC we'll always find old regions to add to the CSet (i.e., it eliminates the case where a mixed GC will collect no old regions which can happen today). Reviewed-by: johnc, brutisso
author tonyp
date Wed, 15 Feb 2012 13:06:53 -0500
parents eff609af17d7
children 21595f05bc93
comparison
equal deleted inserted replaced
4911:d903bf750e9f 4912:a9647476d1a4
204 204
205 _all_full_gc_times_ms(new NumberSeq()), 205 _all_full_gc_times_ms(new NumberSeq()),
206 206
207 _initiate_conc_mark_if_possible(false), 207 _initiate_conc_mark_if_possible(false),
208 _during_initial_mark_pause(false), 208 _during_initial_mark_pause(false),
209 _should_revert_to_young_gcs(false),
210 _last_young_gc(false), 209 _last_young_gc(false),
211 _last_gc_was_young(false), 210 _last_gc_was_young(false),
212 211
213 _eden_bytes_before_gc(0), 212 _eden_bytes_before_gc(0),
214 _survivor_bytes_before_gc(0), 213 _survivor_bytes_before_gc(0),
292 _par_last_termination_times_ms = new double[_parallel_gc_threads]; 291 _par_last_termination_times_ms = new double[_parallel_gc_threads];
293 _par_last_termination_attempts = new double[_parallel_gc_threads]; 292 _par_last_termination_attempts = new double[_parallel_gc_threads];
294 _par_last_gc_worker_end_times_ms = new double[_parallel_gc_threads]; 293 _par_last_gc_worker_end_times_ms = new double[_parallel_gc_threads];
295 _par_last_gc_worker_times_ms = new double[_parallel_gc_threads]; 294 _par_last_gc_worker_times_ms = new double[_parallel_gc_threads];
296 _par_last_gc_worker_other_times_ms = new double[_parallel_gc_threads]; 295 _par_last_gc_worker_other_times_ms = new double[_parallel_gc_threads];
297
298 // start conservatively
299 _expensive_region_limit_ms = 0.5 * (double) MaxGCPauseMillis;
300 296
301 int index; 297 int index;
302 if (ParallelGCThreads == 0) 298 if (ParallelGCThreads == 0)
303 index = 0; 299 index = 0;
304 else if (ParallelGCThreads > 8) 300 else if (ParallelGCThreads > 8)
627 // Don't calculate anything and let the code below bound it to 623 // Don't calculate anything and let the code below bound it to
628 // the desired_min_length, i.e., do the next GC as soon as 624 // the desired_min_length, i.e., do the next GC as soon as
629 // possible to maximize how many old regions we can add to it. 625 // possible to maximize how many old regions we can add to it.
630 } 626 }
631 } else { 627 } else {
632 if (gcs_are_young()) { 628 // The user asked for a fixed young gen so we'll fix the young gen
633 young_list_target_length = _young_list_fixed_length; 629 // whether the next GC is young or mixed.
634 } else { 630 young_list_target_length = _young_list_fixed_length;
635 // A bit arbitrary: during mixed GCs we allocate half
636 // the young regions to try to add old regions to the CSet.
637 young_list_target_length = _young_list_fixed_length / 2;
638 // We choose to accept that we might go under the desired min
639 // length given that we intentionally ask for a smaller young gen.
640 desired_min_length = absolute_min_length;
641 }
642 } 631 }
643 632
644 // Make sure we don't go over the desired max length, nor under the 633 // Make sure we don't go over the desired max length, nor under the
645 // desired min length. In case they clash, desired_min_length wins 634 // desired min length. In case they clash, desired_min_length wins
646 // which is why that test is second. 635 // which is why that test is second.
870 859
871 // "Nuke" the heuristics that control the young/mixed GC 860 // "Nuke" the heuristics that control the young/mixed GC
872 // transitions and make sure we start with young GCs after the Full GC. 861 // transitions and make sure we start with young GCs after the Full GC.
873 set_gcs_are_young(true); 862 set_gcs_are_young(true);
874 _last_young_gc = false; 863 _last_young_gc = false;
875 _should_revert_to_young_gcs = false;
876 clear_initiate_conc_mark_if_possible(); 864 clear_initiate_conc_mark_if_possible();
877 clear_during_initial_mark_pause(); 865 clear_during_initial_mark_pause();
878 _known_garbage_bytes = 0; 866 _known_garbage_bytes = 0;
879 _known_garbage_ratio = 0.0; 867 _known_garbage_ratio = 0.0;
880 _in_marking_window = false; 868 _in_marking_window = false;
887 875
888 _free_regions_at_end_of_collection = _g1->free_regions(); 876 _free_regions_at_end_of_collection = _g1->free_regions();
889 // Reset survivors SurvRateGroup. 877 // Reset survivors SurvRateGroup.
890 _survivor_surv_rate_group->reset(); 878 _survivor_surv_rate_group->reset();
891 update_young_list_target_length(); 879 update_young_list_target_length();
892 _collectionSetChooser->updateAfterFullCollection(); 880 _collectionSetChooser->clearMarkedHeapRegions();
893 } 881 }
894 882
895 void G1CollectorPolicy::record_stop_world_start() { 883 void G1CollectorPolicy::record_stop_world_start() {
896 _stop_world_start = os::elapsedTime(); 884 _stop_world_start = os::elapsedTime();
897 } 885 }
998 void G1CollectorPolicy::record_concurrent_mark_cleanup_start() { 986 void G1CollectorPolicy::record_concurrent_mark_cleanup_start() {
999 _mark_cleanup_start_sec = os::elapsedTime(); 987 _mark_cleanup_start_sec = os::elapsedTime();
1000 } 988 }
1001 989
1002 void G1CollectorPolicy::record_concurrent_mark_cleanup_completed() { 990 void G1CollectorPolicy::record_concurrent_mark_cleanup_completed() {
1003 _should_revert_to_young_gcs = false;
1004 _last_young_gc = true; 991 _last_young_gc = true;
1005 _in_marking_window = false; 992 _in_marking_window = false;
1006 } 993 }
1007 994
1008 void G1CollectorPolicy::record_concurrent_pause() { 995 void G1CollectorPolicy::record_concurrent_pause() {
1203 #endif // PRODUCT 1190 #endif // PRODUCT
1204 1191
1205 last_pause_included_initial_mark = during_initial_mark_pause(); 1192 last_pause_included_initial_mark = during_initial_mark_pause();
1206 if (last_pause_included_initial_mark) { 1193 if (last_pause_included_initial_mark) {
1207 record_concurrent_mark_init_end(0.0); 1194 record_concurrent_mark_init_end(0.0);
1208 } 1195 } else if (!_last_young_gc && need_to_start_conc_mark("end of GC")) {
1209
1210 if (!_last_young_gc && need_to_start_conc_mark("end of GC")) {
1211 // Note: this might have already been set, if during the last 1196 // Note: this might have already been set, if during the last
1212 // pause we decided to start a cycle but at the beginning of 1197 // pause we decided to start a cycle but at the beginning of
1213 // this pause we decided to postpone it. That's OK. 1198 // this pause we decided to postpone it. That's OK.
1214 set_initiate_conc_mark_if_possible(); 1199 set_initiate_conc_mark_if_possible();
1215 } 1200 }
1490 new_in_marking_window = true; 1475 new_in_marking_window = true;
1491 new_in_marking_window_im = true; 1476 new_in_marking_window_im = true;
1492 } 1477 }
1493 1478
1494 if (_last_young_gc) { 1479 if (_last_young_gc) {
1480 // This is supposed to to be the "last young GC" before we start
1481 // doing mixed GCs. Here we decide whether to start mixed GCs or not.
1482
1495 if (!last_pause_included_initial_mark) { 1483 if (!last_pause_included_initial_mark) {
1496 ergo_verbose2(ErgoMixedGCs, 1484 if (next_gc_should_be_mixed("start mixed GCs",
1497 "start mixed GCs", 1485 "do not start mixed GCs")) {
1498 ergo_format_byte_perc("known garbage"), 1486 set_gcs_are_young(false);
1499 _known_garbage_bytes, _known_garbage_ratio * 100.0); 1487 }
1500 set_gcs_are_young(false);
1501 } else { 1488 } else {
1502 ergo_verbose0(ErgoMixedGCs, 1489 ergo_verbose0(ErgoMixedGCs,
1503 "do not start mixed GCs", 1490 "do not start mixed GCs",
1504 ergo_format_reason("concurrent cycle is about to start")); 1491 ergo_format_reason("concurrent cycle is about to start"));
1505 } 1492 }
1506 _last_young_gc = false; 1493 _last_young_gc = false;
1507 } 1494 }
1508 1495
1509 if (!_last_gc_was_young) { 1496 if (!_last_gc_was_young) {
1510 if (_should_revert_to_young_gcs) { 1497 // This is a mixed GC. Here we decide whether to continue doing
1511 ergo_verbose2(ErgoMixedGCs, 1498 // mixed GCs or not.
1512 "end mixed GCs", 1499
1513 ergo_format_reason("mixed GCs end requested") 1500 if (!next_gc_should_be_mixed("continue mixed GCs",
1514 ergo_format_byte_perc("known garbage"), 1501 "do not continue mixed GCs")) {
1515 _known_garbage_bytes, _known_garbage_ratio * 100.0);
1516 set_gcs_are_young(true); 1502 set_gcs_are_young(true);
1517 } else if (_known_garbage_ratio < 0.05) { 1503 }
1518 ergo_verbose3(ErgoMixedGCs, 1504 }
1519 "end mixed GCs",
1520 ergo_format_reason("known garbage percent lower than threshold")
1521 ergo_format_byte_perc("known garbage")
1522 ergo_format_perc("threshold"),
1523 _known_garbage_bytes, _known_garbage_ratio * 100.0,
1524 0.05 * 100.0);
1525 set_gcs_are_young(true);
1526 } else if (adaptive_young_list_length() &&
1527 (get_gc_eff_factor() * cur_efficiency < predict_young_gc_eff())) {
1528 ergo_verbose5(ErgoMixedGCs,
1529 "end mixed GCs",
1530 ergo_format_reason("current GC efficiency lower than "
1531 "predicted young GC efficiency")
1532 ergo_format_double("GC efficiency factor")
1533 ergo_format_double("current GC efficiency")
1534 ergo_format_double("predicted young GC efficiency")
1535 ergo_format_byte_perc("known garbage"),
1536 get_gc_eff_factor(), cur_efficiency,
1537 predict_young_gc_eff(),
1538 _known_garbage_bytes, _known_garbage_ratio * 100.0);
1539 set_gcs_are_young(true);
1540 }
1541 }
1542 _should_revert_to_young_gcs = false;
1543 1505
1544 if (_last_gc_was_young && !_during_marking) { 1506 if (_last_gc_was_young && !_during_marking) {
1545 _young_gc_eff_seq->add(cur_efficiency); 1507 _young_gc_eff_seq->add(cur_efficiency);
1546 } 1508 }
1547 1509
1646 (double) _bytes_in_collection_set_before_gc; 1608 (double) _bytes_in_collection_set_before_gc;
1647 } 1609 }
1648 1610
1649 _pending_cards_seq->add((double) _pending_cards); 1611 _pending_cards_seq->add((double) _pending_cards);
1650 _rs_lengths_seq->add((double) _max_rs_lengths); 1612 _rs_lengths_seq->add((double) _max_rs_lengths);
1651
1652 double expensive_region_limit_ms =
1653 (double) MaxGCPauseMillis - predict_constant_other_time_ms();
1654 if (expensive_region_limit_ms < 0.0) {
1655 // this means that the other time was predicted to be longer than
1656 // than the max pause time
1657 expensive_region_limit_ms = (double) MaxGCPauseMillis;
1658 }
1659 _expensive_region_limit_ms = expensive_region_limit_ms;
1660 } 1613 }
1661 1614
1662 _in_marking_window = new_in_marking_window; 1615 _in_marking_window = new_in_marking_window;
1663 _in_marking_window_im = new_in_marking_window_im; 1616 _in_marking_window_im = new_in_marking_window_im;
1664 _free_regions_at_end_of_collection = _g1->free_regions(); 1617 _free_regions_at_end_of_collection = _g1->free_regions();
1836 G1CollectorPolicy::predict_bytes_to_copy(HeapRegion* hr) { 1789 G1CollectorPolicy::predict_bytes_to_copy(HeapRegion* hr) {
1837 size_t bytes_to_copy; 1790 size_t bytes_to_copy;
1838 if (hr->is_marked()) 1791 if (hr->is_marked())
1839 bytes_to_copy = hr->max_live_bytes(); 1792 bytes_to_copy = hr->max_live_bytes();
1840 else { 1793 else {
1841 guarantee( hr->is_young() && hr->age_in_surv_rate_group() != -1, 1794 assert(hr->is_young() && hr->age_in_surv_rate_group() != -1, "invariant");
1842 "invariant" );
1843 int age = hr->age_in_surv_rate_group(); 1795 int age = hr->age_in_surv_rate_group();
1844 double yg_surv_rate = predict_yg_surv_rate(age, hr->surv_rate_group()); 1796 double yg_surv_rate = predict_yg_surv_rate(age, hr->surv_rate_group());
1845 bytes_to_copy = (size_t) ((double) hr->used() * yg_surv_rate); 1797 bytes_to_copy = (size_t) ((double) hr->used() * yg_surv_rate);
1846 } 1798 }
1847
1848 return bytes_to_copy; 1799 return bytes_to_copy;
1849 } 1800 }
1850 1801
1851 void 1802 void
1852 G1CollectorPolicy::init_cset_region_lengths(size_t eden_cset_region_length, 1803 G1CollectorPolicy::init_cset_region_lengths(size_t eden_cset_region_length,
1856 _old_cset_region_length = 0; 1807 _old_cset_region_length = 0;
1857 } 1808 }
1858 1809
1859 void G1CollectorPolicy::set_recorded_rs_lengths(size_t rs_lengths) { 1810 void G1CollectorPolicy::set_recorded_rs_lengths(size_t rs_lengths) {
1860 _recorded_rs_lengths = rs_lengths; 1811 _recorded_rs_lengths = rs_lengths;
1861 }
1862
1863 void G1CollectorPolicy::check_if_region_is_too_expensive(double
1864 predicted_time_ms) {
1865 // I don't think we need to do this when in young GC mode since
1866 // marking will be initiated next time we hit the soft limit anyway...
1867 if (predicted_time_ms > _expensive_region_limit_ms) {
1868 ergo_verbose2(ErgoMixedGCs,
1869 "request mixed GCs end",
1870 ergo_format_reason("predicted region time higher than threshold")
1871 ergo_format_ms("predicted region time")
1872 ergo_format_ms("threshold"),
1873 predicted_time_ms, _expensive_region_limit_ms);
1874 // no point in doing another mixed GC
1875 _should_revert_to_young_gcs = true;
1876 }
1877 } 1812 }
1878 1813
1879 void G1CollectorPolicy::update_recent_gc_times(double end_time_sec, 1814 void G1CollectorPolicy::update_recent_gc_times(double end_time_sec,
1880 double elapsed_ms) { 1815 double elapsed_ms) {
1881 _recent_gc_times_ms->add(elapsed_ms); 1816 _recent_gc_times_ms->add(elapsed_ms);
2272 } 2207 }
2273 } 2208 }
2274 } 2209 }
2275 2210
2276 class KnownGarbageClosure: public HeapRegionClosure { 2211 class KnownGarbageClosure: public HeapRegionClosure {
2212 G1CollectedHeap* _g1h;
2277 CollectionSetChooser* _hrSorted; 2213 CollectionSetChooser* _hrSorted;
2278 2214
2279 public: 2215 public:
2280 KnownGarbageClosure(CollectionSetChooser* hrSorted) : 2216 KnownGarbageClosure(CollectionSetChooser* hrSorted) :
2281 _hrSorted(hrSorted) 2217 _g1h(G1CollectedHeap::heap()), _hrSorted(hrSorted) { }
2282 {}
2283 2218
2284 bool doHeapRegion(HeapRegion* r) { 2219 bool doHeapRegion(HeapRegion* r) {
2285 // We only include humongous regions in collection 2220 // We only include humongous regions in collection
2286 // sets when concurrent mark shows that their contained object is 2221 // sets when concurrent mark shows that their contained object is
2287 // unreachable. 2222 // unreachable.
2288 2223
2289 // Do we have any marking information for this region? 2224 // Do we have any marking information for this region?
2290 if (r->is_marked()) { 2225 if (r->is_marked()) {
2291 // We don't include humongous regions in collection 2226 // We will skip any region that's currently used as an old GC
2292 // sets because we collect them immediately at the end of a marking 2227 // alloc region (we should not consider those for collection
2293 // cycle. We also don't include young regions because we *must* 2228 // before we fill them up).
2294 // include them in the next collection pause. 2229 if (_hrSorted->shouldAdd(r) && !_g1h->is_old_gc_alloc_region(r)) {
2295 if (!r->isHumongous() && !r->is_young()) {
2296 _hrSorted->addMarkedHeapRegion(r); 2230 _hrSorted->addMarkedHeapRegion(r);
2297 } 2231 }
2298 } 2232 }
2299 return false; 2233 return false;
2300 } 2234 }
2301 }; 2235 };
2302 2236
2303 class ParKnownGarbageHRClosure: public HeapRegionClosure { 2237 class ParKnownGarbageHRClosure: public HeapRegionClosure {
2238 G1CollectedHeap* _g1h;
2304 CollectionSetChooser* _hrSorted; 2239 CollectionSetChooser* _hrSorted;
2305 jint _marked_regions_added; 2240 jint _marked_regions_added;
2241 size_t _reclaimable_bytes_added;
2306 jint _chunk_size; 2242 jint _chunk_size;
2307 jint _cur_chunk_idx; 2243 jint _cur_chunk_idx;
2308 jint _cur_chunk_end; // Cur chunk [_cur_chunk_idx, _cur_chunk_end) 2244 jint _cur_chunk_end; // Cur chunk [_cur_chunk_idx, _cur_chunk_end)
2309 int _worker; 2245 int _worker;
2310 int _invokes; 2246 int _invokes;
2318 get_new_chunk(); 2254 get_new_chunk();
2319 } 2255 }
2320 assert(_cur_chunk_idx < _cur_chunk_end, "postcondition"); 2256 assert(_cur_chunk_idx < _cur_chunk_end, "postcondition");
2321 _hrSorted->setMarkedHeapRegion(_cur_chunk_idx, r); 2257 _hrSorted->setMarkedHeapRegion(_cur_chunk_idx, r);
2322 _marked_regions_added++; 2258 _marked_regions_added++;
2259 _reclaimable_bytes_added += r->reclaimable_bytes();
2323 _cur_chunk_idx++; 2260 _cur_chunk_idx++;
2324 } 2261 }
2325 2262
2326 public: 2263 public:
2327 ParKnownGarbageHRClosure(CollectionSetChooser* hrSorted, 2264 ParKnownGarbageHRClosure(CollectionSetChooser* hrSorted,
2328 jint chunk_size, 2265 jint chunk_size,
2329 int worker) : 2266 int worker) :
2330 _hrSorted(hrSorted), _chunk_size(chunk_size), _worker(worker), 2267 _g1h(G1CollectedHeap::heap()),
2331 _marked_regions_added(0), _cur_chunk_idx(0), _cur_chunk_end(0), 2268 _hrSorted(hrSorted), _chunk_size(chunk_size), _worker(worker),
2332 _invokes(0) 2269 _marked_regions_added(0), _reclaimable_bytes_added(0),
2333 {} 2270 _cur_chunk_idx(0), _cur_chunk_end(0), _invokes(0) { }
2334 2271
2335 bool doHeapRegion(HeapRegion* r) { 2272 bool doHeapRegion(HeapRegion* r) {
2336 // We only include humongous regions in collection 2273 // We only include humongous regions in collection
2337 // sets when concurrent mark shows that their contained object is 2274 // sets when concurrent mark shows that their contained object is
2338 // unreachable. 2275 // unreachable.
2339 _invokes++; 2276 _invokes++;
2340 2277
2341 // Do we have any marking information for this region? 2278 // Do we have any marking information for this region?
2342 if (r->is_marked()) { 2279 if (r->is_marked()) {
2343 // We don't include humongous regions in collection 2280 // We will skip any region that's currently used as an old GC
2344 // sets because we collect them immediately at the end of a marking 2281 // alloc region (we should not consider those for collection
2345 // cycle. 2282 // before we fill them up).
2346 // We also do not include young regions in collection sets 2283 if (_hrSorted->shouldAdd(r) && !_g1h->is_old_gc_alloc_region(r)) {
2347 if (!r->isHumongous() && !r->is_young()) {
2348 add_region(r); 2284 add_region(r);
2349 } 2285 }
2350 } 2286 }
2351 return false; 2287 return false;
2352 } 2288 }
2353 jint marked_regions_added() { return _marked_regions_added; } 2289 jint marked_regions_added() { return _marked_regions_added; }
2290 size_t reclaimable_bytes_added() { return _reclaimable_bytes_added; }
2354 int invokes() { return _invokes; } 2291 int invokes() { return _invokes; }
2355 }; 2292 };
2356 2293
2357 class ParKnownGarbageTask: public AbstractGangTask { 2294 class ParKnownGarbageTask: public AbstractGangTask {
2358 CollectionSetChooser* _hrSorted; 2295 CollectionSetChooser* _hrSorted;
2360 G1CollectedHeap* _g1; 2297 G1CollectedHeap* _g1;
2361 public: 2298 public:
2362 ParKnownGarbageTask(CollectionSetChooser* hrSorted, jint chunk_size) : 2299 ParKnownGarbageTask(CollectionSetChooser* hrSorted, jint chunk_size) :
2363 AbstractGangTask("ParKnownGarbageTask"), 2300 AbstractGangTask("ParKnownGarbageTask"),
2364 _hrSorted(hrSorted), _chunk_size(chunk_size), 2301 _hrSorted(hrSorted), _chunk_size(chunk_size),
2365 _g1(G1CollectedHeap::heap()) 2302 _g1(G1CollectedHeap::heap()) { }
2366 {}
2367 2303
2368 void work(uint worker_id) { 2304 void work(uint worker_id) {
2369 ParKnownGarbageHRClosure parKnownGarbageCl(_hrSorted, 2305 ParKnownGarbageHRClosure parKnownGarbageCl(_hrSorted,
2370 _chunk_size, 2306 _chunk_size,
2371 worker_id); 2307 worker_id);
2372 // Back to zero for the claim value. 2308 // Back to zero for the claim value.
2373 _g1->heap_region_par_iterate_chunked(&parKnownGarbageCl, worker_id, 2309 _g1->heap_region_par_iterate_chunked(&parKnownGarbageCl, worker_id,
2374 _g1->workers()->active_workers(), 2310 _g1->workers()->active_workers(),
2375 HeapRegion::InitialClaimValue); 2311 HeapRegion::InitialClaimValue);
2376 jint regions_added = parKnownGarbageCl.marked_regions_added(); 2312 jint regions_added = parKnownGarbageCl.marked_regions_added();
2377 _hrSorted->incNumMarkedHeapRegions(regions_added); 2313 size_t reclaimable_bytes_added =
2314 parKnownGarbageCl.reclaimable_bytes_added();
2315 _hrSorted->updateTotals(regions_added, reclaimable_bytes_added);
2378 if (G1PrintParCleanupStats) { 2316 if (G1PrintParCleanupStats) {
2379 gclog_or_tty->print_cr(" Thread %d called %d times, added %d regions to list.", 2317 gclog_or_tty->print_cr(" Thread %d called %d times, added %d regions to list.",
2380 worker_id, parKnownGarbageCl.invokes(), regions_added); 2318 worker_id, parKnownGarbageCl.invokes(), regions_added);
2381 } 2319 }
2382 } 2320 }
2656 csr = next; 2594 csr = next;
2657 } 2595 }
2658 } 2596 }
2659 #endif // !PRODUCT 2597 #endif // !PRODUCT
2660 2598
2661 void G1CollectorPolicy::choose_collection_set(double target_pause_time_ms) { 2599 bool G1CollectorPolicy::next_gc_should_be_mixed(const char* true_action_str,
2600 const char* false_action_str) {
2601 CollectionSetChooser* cset_chooser = _collectionSetChooser;
2602 if (cset_chooser->isEmpty()) {
2603 ergo_verbose0(ErgoMixedGCs,
2604 false_action_str,
2605 ergo_format_reason("candidate old regions not available"));
2606 return false;
2607 }
2608 size_t reclaimable_bytes = cset_chooser->remainingReclaimableBytes();
2609 size_t capacity_bytes = _g1->capacity();
2610 double perc = (double) reclaimable_bytes * 100.0 / (double) capacity_bytes;
2611 double threshold = (double) G1OldReclaimableThresholdPercent;
2612 if (perc < threshold) {
2613 ergo_verbose4(ErgoMixedGCs,
2614 false_action_str,
2615 ergo_format_reason("reclaimable percentage lower than threshold")
2616 ergo_format_region("candidate old regions")
2617 ergo_format_byte_perc("reclaimable")
2618 ergo_format_perc("threshold"),
2619 cset_chooser->remainingRegions(),
2620 reclaimable_bytes, perc, threshold);
2621 return false;
2622 }
2623
2624 ergo_verbose4(ErgoMixedGCs,
2625 true_action_str,
2626 ergo_format_reason("candidate old regions available")
2627 ergo_format_region("candidate old regions")
2628 ergo_format_byte_perc("reclaimable")
2629 ergo_format_perc("threshold"),
2630 cset_chooser->remainingRegions(),
2631 reclaimable_bytes, perc, threshold);
2632 return true;
2633 }
2634
2635 void G1CollectorPolicy::finalize_cset(double target_pause_time_ms) {
2662 // Set this here - in case we're not doing young collections. 2636 // Set this here - in case we're not doing young collections.
2663 double non_young_start_time_sec = os::elapsedTime(); 2637 double non_young_start_time_sec = os::elapsedTime();
2664 2638
2665 YoungList* young_list = _g1->young_list(); 2639 YoungList* young_list = _g1->young_list();
2666 finalize_incremental_cset_building(); 2640 finalize_incremental_cset_building();
2670 target_pause_time_ms)); 2644 target_pause_time_ms));
2671 guarantee(_collection_set == NULL, "Precondition"); 2645 guarantee(_collection_set == NULL, "Precondition");
2672 2646
2673 double base_time_ms = predict_base_elapsed_time_ms(_pending_cards); 2647 double base_time_ms = predict_base_elapsed_time_ms(_pending_cards);
2674 double predicted_pause_time_ms = base_time_ms; 2648 double predicted_pause_time_ms = base_time_ms;
2675
2676 double time_remaining_ms = target_pause_time_ms - base_time_ms; 2649 double time_remaining_ms = target_pause_time_ms - base_time_ms;
2677 2650
2678 ergo_verbose3(ErgoCSetConstruction | ErgoHigh, 2651 ergo_verbose3(ErgoCSetConstruction | ErgoHigh,
2679 "start choosing CSet", 2652 "start choosing CSet",
2680 ergo_format_ms("predicted base time") 2653 ergo_format_ms("predicted base time")
2681 ergo_format_ms("remaining time") 2654 ergo_format_ms("remaining time")
2682 ergo_format_ms("target pause time"), 2655 ergo_format_ms("target pause time"),
2683 base_time_ms, time_remaining_ms, target_pause_time_ms); 2656 base_time_ms, time_remaining_ms, target_pause_time_ms);
2684
2685 // the 10% and 50% values are arbitrary...
2686 double threshold = 0.10 * target_pause_time_ms;
2687 if (time_remaining_ms < threshold) {
2688 double prev_time_remaining_ms = time_remaining_ms;
2689 time_remaining_ms = 0.50 * target_pause_time_ms;
2690 ergo_verbose3(ErgoCSetConstruction,
2691 "adjust remaining time",
2692 ergo_format_reason("remaining time lower than threshold")
2693 ergo_format_ms("remaining time")
2694 ergo_format_ms("threshold")
2695 ergo_format_ms("adjusted remaining time"),
2696 prev_time_remaining_ms, threshold, time_remaining_ms);
2697 }
2698
2699 size_t expansion_bytes = _g1->expansion_regions() * HeapRegion::GrainBytes;
2700 2657
2701 HeapRegion* hr; 2658 HeapRegion* hr;
2702 double young_start_time_sec = os::elapsedTime(); 2659 double young_start_time_sec = os::elapsedTime();
2703 2660
2704 _collection_set_bytes_used_before = 0; 2661 _collection_set_bytes_used_before = 0;
2750 2707
2751 // We are doing young collections so reset this. 2708 // We are doing young collections so reset this.
2752 non_young_start_time_sec = young_end_time_sec; 2709 non_young_start_time_sec = young_end_time_sec;
2753 2710
2754 if (!gcs_are_young()) { 2711 if (!gcs_are_young()) {
2755 bool should_continue = true; 2712 CollectionSetChooser* cset_chooser = _collectionSetChooser;
2756 NumberSeq seq; 2713 assert(cset_chooser->verify(), "CSet Chooser verification - pre");
2757 double avg_prediction = 100000000000000000.0; // something very large 2714 const size_t min_old_cset_length = cset_chooser->calcMinOldCSetLength();
2758 2715 const size_t max_old_cset_length = cset_chooser->calcMaxOldCSetLength();
2759 double prev_predicted_pause_time_ms = predicted_pause_time_ms; 2716
2760 do { 2717 size_t expensive_region_num = 0;
2761 // Note that add_old_region_to_cset() increments the 2718 bool check_time_remaining = adaptive_young_list_length();
2762 // _old_cset_region_length field and cset_region_length() returns the 2719 HeapRegion* hr = cset_chooser->peek();
2763 // sum of _eden_cset_region_length, _survivor_cset_region_length, and 2720 while (hr != NULL) {
2764 // _old_cset_region_length. So, as old regions are added to the 2721 if (old_cset_region_length() >= max_old_cset_length) {
2765 // CSet, _old_cset_region_length will be incremented and 2722 // Added maximum number of old regions to the CSet.
2766 // cset_region_length(), which is used below, will always reflect 2723 ergo_verbose2(ErgoCSetConstruction,
2767 // the the total number of regions added up to this point to the CSet. 2724 "finish adding old regions to CSet",
2768 2725 ergo_format_reason("old CSet region num reached max")
2769 hr = _collectionSetChooser->getNextMarkedRegion(time_remaining_ms, 2726 ergo_format_region("old")
2770 avg_prediction); 2727 ergo_format_region("max"),
2771 if (hr != NULL) { 2728 old_cset_region_length(), max_old_cset_length);
2772 _g1->old_set_remove(hr); 2729 break;
2773 double predicted_time_ms = predict_region_elapsed_time_ms(hr, false);
2774 time_remaining_ms -= predicted_time_ms;
2775 predicted_pause_time_ms += predicted_time_ms;
2776 add_old_region_to_cset(hr);
2777 seq.add(predicted_time_ms);
2778 avg_prediction = seq.avg() + seq.sd();
2779 } 2730 }
2780 2731
2781 should_continue = true; 2732 double predicted_time_ms = predict_region_elapsed_time_ms(hr, false);
2782 if (hr == NULL) { 2733 if (check_time_remaining) {
2783 // No need for an ergo verbose message here, 2734 if (predicted_time_ms > time_remaining_ms) {
2784 // getNextMarkRegion() does this when it returns NULL. 2735 // Too expensive for the current CSet.
2785 should_continue = false; 2736
2737 if (old_cset_region_length() >= min_old_cset_length) {
2738 // We have added the minimum number of old regions to the CSet,
2739 // we are done with this CSet.
2740 ergo_verbose4(ErgoCSetConstruction,
2741 "finish adding old regions to CSet",
2742 ergo_format_reason("predicted time is too high")
2743 ergo_format_ms("predicted time")
2744 ergo_format_ms("remaining time")
2745 ergo_format_region("old")
2746 ergo_format_region("min"),
2747 predicted_time_ms, time_remaining_ms,
2748 old_cset_region_length(), min_old_cset_length);
2749 break;
2750 }
2751
2752 // We'll add it anyway given that we haven't reached the
2753 // minimum number of old regions.
2754 expensive_region_num += 1;
2755 }
2786 } else { 2756 } else {
2787 if (adaptive_young_list_length()) { 2757 if (old_cset_region_length() >= min_old_cset_length) {
2788 if (time_remaining_ms < 0.0) { 2758 // In the non-auto-tuning case, we'll finish adding regions
2789 ergo_verbose1(ErgoCSetConstruction, 2759 // to the CSet if we reach the minimum.
2790 "stop adding old regions to CSet", 2760 ergo_verbose2(ErgoCSetConstruction,
2791 ergo_format_reason("remaining time is lower than 0") 2761 "finish adding old regions to CSet",
2792 ergo_format_ms("remaining time"), 2762 ergo_format_reason("old CSet region num reached min")
2793 time_remaining_ms); 2763 ergo_format_region("old")
2794 should_continue = false; 2764 ergo_format_region("min"),
2795 } 2765 old_cset_region_length(), min_old_cset_length);
2796 } else { 2766 break;
2797 if (cset_region_length() >= _young_list_fixed_length) {
2798 ergo_verbose2(ErgoCSetConstruction,
2799 "stop adding old regions to CSet",
2800 ergo_format_reason("CSet length reached target")
2801 ergo_format_region("CSet")
2802 ergo_format_region("young target"),
2803 cset_region_length(), _young_list_fixed_length);
2804 should_continue = false;
2805 }
2806 } 2767 }
2807 } 2768 }
2808 } while (should_continue); 2769
2809 2770 // We will add this region to the CSet.
2810 if (!adaptive_young_list_length() && 2771 time_remaining_ms -= predicted_time_ms;
2811 cset_region_length() < _young_list_fixed_length) { 2772 predicted_pause_time_ms += predicted_time_ms;
2812 ergo_verbose2(ErgoCSetConstruction, 2773 cset_chooser->remove_and_move_to_next(hr);
2813 "request mixed GCs end", 2774 _g1->old_set_remove(hr);
2814 ergo_format_reason("CSet length lower than target") 2775 add_old_region_to_cset(hr);
2815 ergo_format_region("CSet") 2776
2816 ergo_format_region("young target"), 2777 hr = cset_chooser->peek();
2817 cset_region_length(), _young_list_fixed_length); 2778 }
2818 _should_revert_to_young_gcs = true; 2779 if (hr == NULL) {
2819 } 2780 ergo_verbose0(ErgoCSetConstruction,
2820 2781 "finish adding old regions to CSet",
2821 ergo_verbose2(ErgoCSetConstruction | ErgoHigh, 2782 ergo_format_reason("candidate old regions not available"));
2822 "add old regions to CSet", 2783 }
2823 ergo_format_region("old") 2784
2824 ergo_format_ms("predicted old region time"), 2785 if (expensive_region_num > 0) {
2825 old_cset_region_length(), 2786 // We print the information once here at the end, predicated on
2826 predicted_pause_time_ms - prev_predicted_pause_time_ms); 2787 // whether we added any apparently expensive regions or not, to
2788 // avoid generating output per region.
2789 ergo_verbose4(ErgoCSetConstruction,
2790 "added expensive regions to CSet",
2791 ergo_format_reason("old CSet region num not reached min")
2792 ergo_format_region("old")
2793 ergo_format_region("expensive")
2794 ergo_format_region("min")
2795 ergo_format_ms("remaining time"),
2796 old_cset_region_length(),
2797 expensive_region_num,
2798 min_old_cset_length,
2799 time_remaining_ms);
2800 }
2801
2802 assert(cset_chooser->verify(), "CSet Chooser verification - post");
2827 } 2803 }
2828 2804
2829 stop_incremental_cset_building(); 2805 stop_incremental_cset_building();
2830 2806
2831 count_CS_bytes_used(); 2807 count_CS_bytes_used();