Mercurial > hg > graal-jvmci-8
comparison src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @ 3914:20213c8a3c40
7050392: G1: Introduce flag to generate a log of the G1 ergonomic decisions
Summary: It introduces ergonomic decision logging in G1 for the following heuristics: heap sizing, collection set construction, concurrent cycle initiation, and partially-young GC start/end. The code has a bit of refactoring in a few places to make the decision logging possible. It also replaces alternative ad-hoc logging that we have under different parameters and switches (G1_DEBUG, G1PolicyVerbose).
Reviewed-by: johnc, ysr
author | tonyp |
---|---|
date | Wed, 07 Sep 2011 12:21:23 -0400 |
parents | ae73da50be4b |
children | 4f41766176cf |
comparison
equal
deleted
inserted
replaced
3913:27702f012017 | 3914:20213c8a3c40 |
---|---|
26 #include "gc_implementation/g1/concurrentG1Refine.hpp" | 26 #include "gc_implementation/g1/concurrentG1Refine.hpp" |
27 #include "gc_implementation/g1/concurrentMark.hpp" | 27 #include "gc_implementation/g1/concurrentMark.hpp" |
28 #include "gc_implementation/g1/concurrentMarkThread.inline.hpp" | 28 #include "gc_implementation/g1/concurrentMarkThread.inline.hpp" |
29 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" | 29 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" |
30 #include "gc_implementation/g1/g1CollectorPolicy.hpp" | 30 #include "gc_implementation/g1/g1CollectorPolicy.hpp" |
31 #include "gc_implementation/g1/g1ErgoVerbose.hpp" | |
31 #include "gc_implementation/g1/heapRegionRemSet.hpp" | 32 #include "gc_implementation/g1/heapRegionRemSet.hpp" |
32 #include "gc_implementation/shared/gcPolicyCounters.hpp" | 33 #include "gc_implementation/shared/gcPolicyCounters.hpp" |
33 #include "runtime/arguments.hpp" | 34 #include "runtime/arguments.hpp" |
34 #include "runtime/java.hpp" | 35 #include "runtime/java.hpp" |
35 #include "runtime/mutexLocker.hpp" | 36 #include "runtime/mutexLocker.hpp" |
269 _recorded_survivor_regions(0), | 270 _recorded_survivor_regions(0), |
270 _recorded_survivor_head(NULL), | 271 _recorded_survivor_head(NULL), |
271 _recorded_survivor_tail(NULL), | 272 _recorded_survivor_tail(NULL), |
272 _survivors_age_table(true), | 273 _survivors_age_table(true), |
273 | 274 |
274 _gc_overhead_perc(0.0) | 275 _gc_overhead_perc(0.0) { |
275 | 276 |
276 { | |
277 // Set up the region size and associated fields. Given that the | 277 // Set up the region size and associated fields. Given that the |
278 // policy is created before the heap, we have to set this up here, | 278 // policy is created before the heap, we have to set this up here, |
279 // so it's done as soon as possible. | 279 // so it's done as soon as possible. |
280 HeapRegion::setup_heap_region_size(Arguments::min_heap_size()); | 280 HeapRegion::setup_heap_region_size(Arguments::min_heap_size()); |
281 HeapRegionRemSet::setup_remset_size(); | 281 HeapRegionRemSet::setup_remset_size(); |
282 | |
283 G1ErgoVerbose::initialize(); | |
284 if (PrintAdaptiveSizePolicy) { | |
285 // Currently, we only use a single switch for all the heuristics. | |
286 G1ErgoVerbose::set_enabled(true); | |
287 // Given that we don't currently have a verboseness level | |
288 // parameter, we'll hardcode this to high. This can be easily | |
289 // changed in the future. | |
290 G1ErgoVerbose::set_level(ErgoHigh); | |
291 } else { | |
292 G1ErgoVerbose::set_enabled(false); | |
293 } | |
282 | 294 |
283 // Verify PLAB sizes | 295 // Verify PLAB sizes |
284 const uint region_size = HeapRegion::GrainWords; | 296 const uint region_size = HeapRegion::GrainWords; |
285 if (YoungPLABSize > region_size || OldPLABSize > region_size) { | 297 if (YoungPLABSize > region_size || OldPLABSize > region_size) { |
286 char buffer[128]; | 298 char buffer[128]; |
957 | 969 |
958 void | 970 void |
959 G1CollectorPolicy:: | 971 G1CollectorPolicy:: |
960 record_concurrent_mark_cleanup_end_work1(size_t freed_bytes, | 972 record_concurrent_mark_cleanup_end_work1(size_t freed_bytes, |
961 size_t max_live_bytes) { | 973 size_t max_live_bytes) { |
962 if (_n_marks < 2) _n_marks++; | 974 if (_n_marks < 2) { |
963 if (G1PolicyVerbose > 0) | 975 _n_marks++; |
964 gclog_or_tty->print_cr("At end of marking, max_live is " SIZE_FORMAT " MB " | 976 } |
965 " (of " SIZE_FORMAT " MB heap).", | |
966 max_live_bytes/M, _g1->capacity()/M); | |
967 } | 977 } |
968 | 978 |
969 // The important thing about this is that it includes "os::elapsedTime". | 979 // The important thing about this is that it includes "os::elapsedTime". |
970 void G1CollectorPolicy::record_concurrent_mark_cleanup_end_work2() { | 980 void G1CollectorPolicy::record_concurrent_mark_cleanup_end_work2() { |
971 double end_time_sec = os::elapsedTime(); | 981 double end_time_sec = os::elapsedTime(); |
975 _prev_collection_pause_end_ms += elapsed_time_ms; | 985 _prev_collection_pause_end_ms += elapsed_time_ms; |
976 | 986 |
977 _mmu_tracker->add_pause(_mark_cleanup_start_sec, end_time_sec, true); | 987 _mmu_tracker->add_pause(_mark_cleanup_start_sec, end_time_sec, true); |
978 | 988 |
979 _num_markings++; | 989 _num_markings++; |
980 | |
981 // We did a marking, so reset the "since_last_mark" variables. | |
982 double considerConcMarkCost = 1.0; | |
983 // If there are available processors, concurrent activity is free... | |
984 if (Threads::number_of_non_daemon_threads() * 2 < | |
985 os::active_processor_count()) { | |
986 considerConcMarkCost = 0.0; | |
987 } | |
988 _n_pauses_at_mark_end = _n_pauses; | 990 _n_pauses_at_mark_end = _n_pauses; |
989 _n_marks_since_last_pause++; | 991 _n_marks_since_last_pause++; |
990 } | 992 } |
991 | 993 |
992 void | 994 void |
1146 | 1148 |
1147 last_pause_included_initial_mark = during_initial_mark_pause(); | 1149 last_pause_included_initial_mark = during_initial_mark_pause(); |
1148 if (last_pause_included_initial_mark) | 1150 if (last_pause_included_initial_mark) |
1149 record_concurrent_mark_init_end(0.0); | 1151 record_concurrent_mark_init_end(0.0); |
1150 | 1152 |
1151 size_t min_used_targ = | 1153 size_t marking_initiating_used_threshold = |
1152 (_g1->capacity() / 100) * InitiatingHeapOccupancyPercent; | 1154 (_g1->capacity() / 100) * InitiatingHeapOccupancyPercent; |
1153 | |
1154 | 1155 |
1155 if (!_g1->mark_in_progress() && !_last_full_young_gc) { | 1156 if (!_g1->mark_in_progress() && !_last_full_young_gc) { |
1156 assert(!last_pause_included_initial_mark, "invariant"); | 1157 assert(!last_pause_included_initial_mark, "invariant"); |
1157 if (cur_used_bytes > min_used_targ && | 1158 if (cur_used_bytes > marking_initiating_used_threshold) { |
1158 cur_used_bytes > _prev_collection_pause_used_at_end_bytes) { | 1159 if (cur_used_bytes > _prev_collection_pause_used_at_end_bytes) { |
1159 assert(!during_initial_mark_pause(), "we should not see this here"); | 1160 assert(!during_initial_mark_pause(), "we should not see this here"); |
1161 | |
1162 ergo_verbose3(ErgoConcCycles, | |
1163 "request concurrent cycle initiation", | |
1164 ergo_format_reason("occupancy higher than threshold") | |
1165 ergo_format_byte("occupancy") | |
1166 ergo_format_byte_perc("threshold"), | |
1167 cur_used_bytes, | |
1168 marking_initiating_used_threshold, | |
1169 (double) InitiatingHeapOccupancyPercent); | |
1160 | 1170 |
1161 // Note: this might have already been set, if during the last | 1171 // Note: this might have already been set, if during the last |
1162 // pause we decided to start a cycle but at the beginning of | 1172 // pause we decided to start a cycle but at the beginning of |
1163 // this pause we decided to postpone it. That's OK. | 1173 // this pause we decided to postpone it. That's OK. |
1164 set_initiate_conc_mark_if_possible(); | 1174 set_initiate_conc_mark_if_possible(); |
1175 } else { | |
1176 ergo_verbose2(ErgoConcCycles, | |
1177 "do not request concurrent cycle initiation", | |
1178 ergo_format_reason("occupancy lower than previous occupancy") | |
1179 ergo_format_byte("occupancy") | |
1180 ergo_format_byte("previous occupancy"), | |
1181 cur_used_bytes, | |
1182 _prev_collection_pause_used_at_end_bytes); | |
1183 } | |
1165 } | 1184 } |
1166 } | 1185 } |
1167 | 1186 |
1168 _prev_collection_pause_used_at_end_bytes = cur_used_bytes; | 1187 _prev_collection_pause_used_at_end_bytes = cur_used_bytes; |
1169 | 1188 |
1435 new_in_marking_window = true; | 1454 new_in_marking_window = true; |
1436 new_in_marking_window_im = true; | 1455 new_in_marking_window_im = true; |
1437 } | 1456 } |
1438 | 1457 |
1439 if (_last_full_young_gc) { | 1458 if (_last_full_young_gc) { |
1459 ergo_verbose2(ErgoPartiallyYoungGCs, | |
1460 "start partially-young GCs", | |
1461 ergo_format_byte_perc("known garbage"), | |
1462 _known_garbage_bytes, _known_garbage_ratio * 100.0); | |
1440 set_full_young_gcs(false); | 1463 set_full_young_gcs(false); |
1441 _last_full_young_gc = false; | 1464 _last_full_young_gc = false; |
1442 } | 1465 } |
1443 | 1466 |
1444 if ( !_last_young_gc_full ) { | 1467 if ( !_last_young_gc_full ) { |
1445 if ( _should_revert_to_full_young_gcs || | 1468 if (_should_revert_to_full_young_gcs) { |
1446 _known_garbage_ratio < 0.05 || | 1469 ergo_verbose2(ErgoPartiallyYoungGCs, |
1447 (adaptive_young_list_length() && | 1470 "end partially-young GCs", |
1448 (get_gc_eff_factor() * cur_efficiency < predict_young_gc_eff())) ) { | 1471 ergo_format_reason("partially-young GCs end requested") |
1449 set_full_young_gcs(true); | 1472 ergo_format_byte_perc("known garbage"), |
1473 _known_garbage_bytes, _known_garbage_ratio * 100.0); | |
1474 set_full_young_gcs(true); | |
1475 } else if (_known_garbage_ratio < 0.05) { | |
1476 ergo_verbose3(ErgoPartiallyYoungGCs, | |
1477 "end partially-young GCs", | |
1478 ergo_format_reason("known garbage percent lower than threshold") | |
1479 ergo_format_byte_perc("known garbage") | |
1480 ergo_format_perc("threshold"), | |
1481 _known_garbage_bytes, _known_garbage_ratio * 100.0, | |
1482 0.05 * 100.0); | |
1483 set_full_young_gcs(true); | |
1484 } else if (adaptive_young_list_length() && | |
1485 (get_gc_eff_factor() * cur_efficiency < predict_young_gc_eff())) { | |
1486 ergo_verbose5(ErgoPartiallyYoungGCs, | |
1487 "end partially-young GCs", | |
1488 ergo_format_reason("current GC efficiency lower than " | |
1489 "predicted fully-young GC efficiency") | |
1490 ergo_format_double("GC efficiency factor") | |
1491 ergo_format_double("current GC efficiency") | |
1492 ergo_format_double("predicted fully-young GC efficiency") | |
1493 ergo_format_byte_perc("known garbage"), | |
1494 get_gc_eff_factor(), cur_efficiency, | |
1495 predict_young_gc_eff(), | |
1496 _known_garbage_bytes, _known_garbage_ratio * 100.0); | |
1497 set_full_young_gcs(true); | |
1450 } | 1498 } |
1451 } | 1499 } |
1452 _should_revert_to_full_young_gcs = false; | 1500 _should_revert_to_full_young_gcs = false; |
1453 | 1501 |
1454 if (_last_young_gc_full && !_during_marking) { | 1502 if (_last_young_gc_full && !_during_marking) { |
1875 void G1CollectorPolicy::check_if_region_is_too_expensive(double | 1923 void G1CollectorPolicy::check_if_region_is_too_expensive(double |
1876 predicted_time_ms) { | 1924 predicted_time_ms) { |
1877 // I don't think we need to do this when in young GC mode since | 1925 // I don't think we need to do this when in young GC mode since |
1878 // marking will be initiated next time we hit the soft limit anyway... | 1926 // marking will be initiated next time we hit the soft limit anyway... |
1879 if (predicted_time_ms > _expensive_region_limit_ms) { | 1927 if (predicted_time_ms > _expensive_region_limit_ms) { |
1928 ergo_verbose2(ErgoPartiallyYoungGCs, | |
1929 "request partially-young GCs end", | |
1930 ergo_format_reason("predicted region time higher than threshold") | |
1931 ergo_format_ms("predicted region time") | |
1932 ergo_format_ms("threshold"), | |
1933 predicted_time_ms, _expensive_region_limit_ms); | |
1880 // no point in doing another partial one | 1934 // no point in doing another partial one |
1881 _should_revert_to_full_young_gcs = true; | 1935 _should_revert_to_full_young_gcs = true; |
1882 } | 1936 } |
1883 } | 1937 } |
1884 | 1938 |
1984 res = MIN2(res, 1.0); | 2038 res = MIN2(res, 1.0); |
1985 return res; | 2039 return res; |
1986 } | 2040 } |
1987 | 2041 |
1988 size_t G1CollectorPolicy::expansion_amount() { | 2042 size_t G1CollectorPolicy::expansion_amount() { |
1989 if ((recent_avg_pause_time_ratio() * 100.0) > _gc_overhead_perc) { | 2043 double recent_gc_overhead = recent_avg_pause_time_ratio() * 100.0; |
2044 double threshold = _gc_overhead_perc; | |
2045 if (recent_gc_overhead > threshold) { | |
1990 // We will double the existing space, or take | 2046 // We will double the existing space, or take |
1991 // G1ExpandByPercentOfAvailable % of the available expansion | 2047 // G1ExpandByPercentOfAvailable % of the available expansion |
1992 // space, whichever is smaller, bounded below by a minimum | 2048 // space, whichever is smaller, bounded below by a minimum |
1993 // expansion (unless that's all that's left.) | 2049 // expansion (unless that's all that's left.) |
1994 const size_t min_expand_bytes = 1*M; | 2050 const size_t min_expand_bytes = 1*M; |
1999 size_t expand_bytes_via_pct = | 2055 size_t expand_bytes_via_pct = |
2000 uncommitted_bytes * G1ExpandByPercentOfAvailable / 100; | 2056 uncommitted_bytes * G1ExpandByPercentOfAvailable / 100; |
2001 expand_bytes = MIN2(expand_bytes_via_pct, committed_bytes); | 2057 expand_bytes = MIN2(expand_bytes_via_pct, committed_bytes); |
2002 expand_bytes = MAX2(expand_bytes, min_expand_bytes); | 2058 expand_bytes = MAX2(expand_bytes, min_expand_bytes); |
2003 expand_bytes = MIN2(expand_bytes, uncommitted_bytes); | 2059 expand_bytes = MIN2(expand_bytes, uncommitted_bytes); |
2004 if (G1PolicyVerbose > 1) { | 2060 |
2005 gclog_or_tty->print("Decided to expand: ratio = %5.2f, " | 2061 ergo_verbose5(ErgoHeapSizing, |
2006 "committed = %d%s, uncommited = %d%s, via pct = %d%s.\n" | 2062 "attempt heap expansion", |
2007 " Answer = %d.\n", | 2063 ergo_format_reason("recent GC overhead higher than " |
2008 recent_avg_pause_time_ratio(), | 2064 "threshold after GC") |
2009 byte_size_in_proper_unit(committed_bytes), | 2065 ergo_format_perc("recent GC overhead") |
2010 proper_unit_for_byte_size(committed_bytes), | 2066 ergo_format_perc("threshold") |
2011 byte_size_in_proper_unit(uncommitted_bytes), | 2067 ergo_format_byte("uncommitted") |
2012 proper_unit_for_byte_size(uncommitted_bytes), | 2068 ergo_format_byte_perc("calculated expansion amount"), |
2013 byte_size_in_proper_unit(expand_bytes_via_pct), | 2069 recent_gc_overhead, threshold, |
2014 proper_unit_for_byte_size(expand_bytes_via_pct), | 2070 uncommitted_bytes, |
2015 byte_size_in_proper_unit(expand_bytes), | 2071 expand_bytes_via_pct, (double) G1ExpandByPercentOfAvailable); |
2016 proper_unit_for_byte_size(expand_bytes)); | 2072 |
2017 } | |
2018 return expand_bytes; | 2073 return expand_bytes; |
2019 } else { | 2074 } else { |
2020 return 0; | 2075 return 0; |
2021 } | 2076 } |
2022 } | 2077 } |
2235 _short_lived_surv_rate_group->print_surv_rate_summary(); | 2290 _short_lived_surv_rate_group->print_surv_rate_summary(); |
2236 // add this call for any other surv rate groups | 2291 // add this call for any other surv rate groups |
2237 #endif // PRODUCT | 2292 #endif // PRODUCT |
2238 } | 2293 } |
2239 | 2294 |
2240 void | 2295 void G1CollectorPolicy::update_region_num(bool young) { |
2241 G1CollectorPolicy::update_region_num(bool young) { | |
2242 if (young) { | 2296 if (young) { |
2243 ++_region_num_young; | 2297 ++_region_num_young; |
2244 } else { | 2298 } else { |
2245 ++_region_num_tenured; | 2299 ++_region_num_tenured; |
2246 } | 2300 } |
2313 _g1->heap_region_iterate(&cl); | 2367 _g1->heap_region_iterate(&cl); |
2314 return true; | 2368 return true; |
2315 } | 2369 } |
2316 #endif | 2370 #endif |
2317 | 2371 |
2318 bool | 2372 bool G1CollectorPolicy::force_initial_mark_if_outside_cycle( |
2319 G1CollectorPolicy::force_initial_mark_if_outside_cycle() { | 2373 GCCause::Cause gc_cause) { |
2320 bool during_cycle = _g1->concurrent_mark()->cmThread()->during_cycle(); | 2374 bool during_cycle = _g1->concurrent_mark()->cmThread()->during_cycle(); |
2321 if (!during_cycle) { | 2375 if (!during_cycle) { |
2376 ergo_verbose1(ErgoConcCycles, | |
2377 "request concurrent cycle initiation", | |
2378 ergo_format_reason("requested by GC cause") | |
2379 ergo_format_str("GC cause"), | |
2380 GCCause::to_string(gc_cause)); | |
2322 set_initiate_conc_mark_if_possible(); | 2381 set_initiate_conc_mark_if_possible(); |
2323 return true; | 2382 return true; |
2324 } else { | 2383 } else { |
2384 ergo_verbose1(ErgoConcCycles, | |
2385 "do not request concurrent cycle initiation", | |
2386 ergo_format_reason("concurrent cycle already in progress") | |
2387 ergo_format_str("GC cause"), | |
2388 GCCause::to_string(gc_cause)); | |
2325 return false; | 2389 return false; |
2326 } | 2390 } |
2327 } | 2391 } |
2328 | 2392 |
2329 void | 2393 void |
2351 set_during_initial_mark_pause(); | 2415 set_during_initial_mark_pause(); |
2352 | 2416 |
2353 // And we can now clear initiate_conc_mark_if_possible() as | 2417 // And we can now clear initiate_conc_mark_if_possible() as |
2354 // we've already acted on it. | 2418 // we've already acted on it. |
2355 clear_initiate_conc_mark_if_possible(); | 2419 clear_initiate_conc_mark_if_possible(); |
2420 | |
2421 ergo_verbose0(ErgoConcCycles, | |
2422 "initiate concurrent cycle", | |
2423 ergo_format_reason("concurrent cycle initiation requested")); | |
2356 } else { | 2424 } else { |
2357 // The concurrent marking thread is still finishing up the | 2425 // The concurrent marking thread is still finishing up the |
2358 // previous cycle. If we start one right now the two cycles | 2426 // previous cycle. If we start one right now the two cycles |
2359 // overlap. In particular, the concurrent marking thread might | 2427 // overlap. In particular, the concurrent marking thread might |
2360 // be in the process of clearing the next marking bitmap (which | 2428 // be in the process of clearing the next marking bitmap (which |
2364 // cannot wait for the marking thread to finish the cycle as it | 2432 // cannot wait for the marking thread to finish the cycle as it |
2365 // periodically yields while clearing the next marking bitmap | 2433 // periodically yields while clearing the next marking bitmap |
2366 // and, if it's in a yield point, it's waiting for us to | 2434 // and, if it's in a yield point, it's waiting for us to |
2367 // finish. So, at this point we will not start a cycle and we'll | 2435 // finish. So, at this point we will not start a cycle and we'll |
2368 // let the concurrent marking thread complete the last one. | 2436 // let the concurrent marking thread complete the last one. |
2437 ergo_verbose0(ErgoConcCycles, | |
2438 "do not initiate concurrent cycle", | |
2439 ergo_format_reason("concurrent cycle already in progress")); | |
2369 } | 2440 } |
2370 } | 2441 } |
2371 } | 2442 } |
2372 | 2443 |
2373 void | 2444 void |
2754 G1CollectorPolicy_BestRegionsFirst::choose_collection_set( | 2825 G1CollectorPolicy_BestRegionsFirst::choose_collection_set( |
2755 double target_pause_time_ms) { | 2826 double target_pause_time_ms) { |
2756 // Set this here - in case we're not doing young collections. | 2827 // Set this here - in case we're not doing young collections. |
2757 double non_young_start_time_sec = os::elapsedTime(); | 2828 double non_young_start_time_sec = os::elapsedTime(); |
2758 | 2829 |
2830 YoungList* young_list = _g1->young_list(); | |
2831 | |
2759 start_recording_regions(); | 2832 start_recording_regions(); |
2760 | 2833 |
2761 guarantee(target_pause_time_ms > 0.0, | 2834 guarantee(target_pause_time_ms > 0.0, |
2762 err_msg("target_pause_time_ms = %1.6lf should be positive", | 2835 err_msg("target_pause_time_ms = %1.6lf should be positive", |
2763 target_pause_time_ms)); | 2836 target_pause_time_ms)); |
2766 double base_time_ms = predict_base_elapsed_time_ms(_pending_cards); | 2839 double base_time_ms = predict_base_elapsed_time_ms(_pending_cards); |
2767 double predicted_pause_time_ms = base_time_ms; | 2840 double predicted_pause_time_ms = base_time_ms; |
2768 | 2841 |
2769 double time_remaining_ms = target_pause_time_ms - base_time_ms; | 2842 double time_remaining_ms = target_pause_time_ms - base_time_ms; |
2770 | 2843 |
2844 ergo_verbose3(ErgoCSetConstruction | ErgoHigh, | |
2845 "start choosing CSet", | |
2846 ergo_format_ms("predicted base time") | |
2847 ergo_format_ms("remaining time") | |
2848 ergo_format_ms("target pause time"), | |
2849 base_time_ms, time_remaining_ms, target_pause_time_ms); | |
2850 | |
2771 // the 10% and 50% values are arbitrary... | 2851 // the 10% and 50% values are arbitrary... |
2772 if (time_remaining_ms < 0.10 * target_pause_time_ms) { | 2852 double threshold = 0.10 * target_pause_time_ms; |
2853 if (time_remaining_ms < threshold) { | |
2854 double prev_time_remaining_ms = time_remaining_ms; | |
2773 time_remaining_ms = 0.50 * target_pause_time_ms; | 2855 time_remaining_ms = 0.50 * target_pause_time_ms; |
2774 _within_target = false; | 2856 _within_target = false; |
2857 ergo_verbose3(ErgoCSetConstruction, | |
2858 "adjust remaining time", | |
2859 ergo_format_reason("remaining time lower than threshold") | |
2860 ergo_format_ms("remaining time") | |
2861 ergo_format_ms("threshold") | |
2862 ergo_format_ms("adjusted remaining time"), | |
2863 prev_time_remaining_ms, threshold, time_remaining_ms); | |
2775 } else { | 2864 } else { |
2776 _within_target = true; | 2865 _within_target = true; |
2777 } | 2866 } |
2778 | 2867 |
2779 // We figure out the number of bytes available for future to-space. | 2868 size_t expansion_bytes = _g1->expansion_regions() * HeapRegion::GrainBytes; |
2780 // For new regions without marking information, we must assume the | 2869 |
2781 // worst-case of complete survival. If we have marking information for a | 2870 HeapRegion* hr; |
2782 // region, we can bound the amount of live data. We can add a number of | 2871 double young_start_time_sec = os::elapsedTime(); |
2783 // such regions, as long as the sum of the live data bounds does not | |
2784 // exceed the available evacuation space. | |
2785 size_t max_live_bytes = _g1->free_regions() * HeapRegion::GrainBytes; | |
2786 | |
2787 size_t expansion_bytes = | |
2788 _g1->expansion_regions() * HeapRegion::GrainBytes; | |
2789 | 2872 |
2790 _collection_set_bytes_used_before = 0; | 2873 _collection_set_bytes_used_before = 0; |
2791 _collection_set_size = 0; | 2874 _collection_set_size = 0; |
2792 | |
2793 // Adjust for expansion and slop. | |
2794 max_live_bytes = max_live_bytes + expansion_bytes; | |
2795 | |
2796 HeapRegion* hr; | |
2797 double young_start_time_sec = os::elapsedTime(); | |
2798 | |
2799 if (G1PolicyVerbose > 0) { | |
2800 gclog_or_tty->print_cr("Adding %d young regions to the CSet", | |
2801 _g1->young_list()->length()); | |
2802 } | |
2803 | |
2804 _young_cset_length = 0; | 2875 _young_cset_length = 0; |
2805 _last_young_gc_full = full_young_gcs() ? true : false; | 2876 _last_young_gc_full = full_young_gcs() ? true : false; |
2806 | 2877 |
2807 if (_last_young_gc_full) | 2878 if (_last_young_gc_full) { |
2808 ++_full_young_pause_num; | 2879 ++_full_young_pause_num; |
2809 else | 2880 } else { |
2810 ++_partial_young_pause_num; | 2881 ++_partial_young_pause_num; |
2882 } | |
2811 | 2883 |
2812 // The young list is laid with the survivor regions from the previous | 2884 // The young list is laid with the survivor regions from the previous |
2813 // pause are appended to the RHS of the young list, i.e. | 2885 // pause are appended to the RHS of the young list, i.e. |
2814 // [Newly Young Regions ++ Survivors from last pause]. | 2886 // [Newly Young Regions ++ Survivors from last pause]. |
2815 | 2887 |
2816 hr = _g1->young_list()->first_survivor_region(); | 2888 size_t survivor_region_num = young_list->survivor_length(); |
2889 size_t eden_region_num = young_list->length() - survivor_region_num; | |
2890 size_t old_region_num = 0; | |
2891 hr = young_list->first_survivor_region(); | |
2817 while (hr != NULL) { | 2892 while (hr != NULL) { |
2818 assert(hr->is_survivor(), "badly formed young list"); | 2893 assert(hr->is_survivor(), "badly formed young list"); |
2819 hr->set_young(); | 2894 hr->set_young(); |
2820 hr = hr->get_next_young_region(); | 2895 hr = hr->get_next_young_region(); |
2821 } | 2896 } |
2822 | 2897 |
2823 // Clear the fields that point to the survivor list - they are | 2898 // Clear the fields that point to the survivor list - they are all young now. |
2824 // all young now. | 2899 young_list->clear_survivors(); |
2825 _g1->young_list()->clear_survivors(); | |
2826 | 2900 |
2827 if (_g1->mark_in_progress()) | 2901 if (_g1->mark_in_progress()) |
2828 _g1->concurrent_mark()->register_collection_set_finger(_inc_cset_max_finger); | 2902 _g1->concurrent_mark()->register_collection_set_finger(_inc_cset_max_finger); |
2829 | 2903 |
2830 _young_cset_length = _inc_cset_young_index; | 2904 _young_cset_length = _inc_cset_young_index; |
2831 _collection_set = _inc_cset_head; | 2905 _collection_set = _inc_cset_head; |
2832 _collection_set_size = _inc_cset_size; | 2906 _collection_set_size = _inc_cset_size; |
2833 _collection_set_bytes_used_before = _inc_cset_bytes_used_before; | 2907 _collection_set_bytes_used_before = _inc_cset_bytes_used_before; |
2834 | |
2835 // For young regions in the collection set, we assume the worst | |
2836 // case of complete survival | |
2837 max_live_bytes -= _inc_cset_size * HeapRegion::GrainBytes; | |
2838 | |
2839 time_remaining_ms -= _inc_cset_predicted_elapsed_time_ms; | 2908 time_remaining_ms -= _inc_cset_predicted_elapsed_time_ms; |
2840 predicted_pause_time_ms += _inc_cset_predicted_elapsed_time_ms; | 2909 predicted_pause_time_ms += _inc_cset_predicted_elapsed_time_ms; |
2910 | |
2911 ergo_verbose3(ErgoCSetConstruction | ErgoHigh, | |
2912 "add young regions to CSet", | |
2913 ergo_format_region("eden") | |
2914 ergo_format_region("survivors") | |
2915 ergo_format_ms("predicted young region time"), | |
2916 eden_region_num, survivor_region_num, | |
2917 _inc_cset_predicted_elapsed_time_ms); | |
2841 | 2918 |
2842 // The number of recorded young regions is the incremental | 2919 // The number of recorded young regions is the incremental |
2843 // collection set's current size | 2920 // collection set's current size |
2844 set_recorded_young_regions(_inc_cset_size); | 2921 set_recorded_young_regions(_inc_cset_size); |
2845 set_recorded_rs_lengths(_inc_cset_recorded_rs_lengths); | 2922 set_recorded_rs_lengths(_inc_cset_recorded_rs_lengths); |
2846 set_recorded_young_bytes(_inc_cset_recorded_young_bytes); | 2923 set_recorded_young_bytes(_inc_cset_recorded_young_bytes); |
2847 #if PREDICTIONS_VERBOSE | 2924 #if PREDICTIONS_VERBOSE |
2848 set_predicted_bytes_to_copy(_inc_cset_predicted_bytes_to_copy); | 2925 set_predicted_bytes_to_copy(_inc_cset_predicted_bytes_to_copy); |
2849 #endif // PREDICTIONS_VERBOSE | 2926 #endif // PREDICTIONS_VERBOSE |
2850 | 2927 |
2851 if (G1PolicyVerbose > 0) { | 2928 assert(_inc_cset_size == young_list->length(), "Invariant"); |
2852 gclog_or_tty->print_cr(" Added " PTR_FORMAT " Young Regions to CS.", | |
2853 _inc_cset_size); | |
2854 gclog_or_tty->print_cr(" (" SIZE_FORMAT " KB left in heap.)", | |
2855 max_live_bytes/K); | |
2856 } | |
2857 | |
2858 assert(_inc_cset_size == _g1->young_list()->length(), "Invariant"); | |
2859 | 2929 |
2860 double young_end_time_sec = os::elapsedTime(); | 2930 double young_end_time_sec = os::elapsedTime(); |
2861 _recorded_young_cset_choice_time_ms = | 2931 _recorded_young_cset_choice_time_ms = |
2862 (young_end_time_sec - young_start_time_sec) * 1000.0; | 2932 (young_end_time_sec - young_start_time_sec) * 1000.0; |
2863 | 2933 |
2867 if (!full_young_gcs()) { | 2937 if (!full_young_gcs()) { |
2868 bool should_continue = true; | 2938 bool should_continue = true; |
2869 NumberSeq seq; | 2939 NumberSeq seq; |
2870 double avg_prediction = 100000000000000000.0; // something very large | 2940 double avg_prediction = 100000000000000000.0; // something very large |
2871 | 2941 |
2942 size_t prev_collection_set_size = _collection_set_size; | |
2943 double prev_predicted_pause_time_ms = predicted_pause_time_ms; | |
2872 do { | 2944 do { |
2873 hr = _collectionSetChooser->getNextMarkedRegion(time_remaining_ms, | 2945 hr = _collectionSetChooser->getNextMarkedRegion(time_remaining_ms, |
2874 avg_prediction); | 2946 avg_prediction); |
2875 if (hr != NULL) { | 2947 if (hr != NULL) { |
2876 double predicted_time_ms = predict_region_elapsed_time_ms(hr, false); | 2948 double predicted_time_ms = predict_region_elapsed_time_ms(hr, false); |
2877 time_remaining_ms -= predicted_time_ms; | 2949 time_remaining_ms -= predicted_time_ms; |
2878 predicted_pause_time_ms += predicted_time_ms; | 2950 predicted_pause_time_ms += predicted_time_ms; |
2879 add_to_collection_set(hr); | 2951 add_to_collection_set(hr); |
2880 record_non_young_cset_region(hr); | 2952 record_non_young_cset_region(hr); |
2881 max_live_bytes -= MIN2(hr->max_live_bytes(), max_live_bytes); | |
2882 if (G1PolicyVerbose > 0) { | |
2883 gclog_or_tty->print_cr(" (" SIZE_FORMAT " KB left in heap.)", | |
2884 max_live_bytes/K); | |
2885 } | |
2886 seq.add(predicted_time_ms); | 2953 seq.add(predicted_time_ms); |
2887 avg_prediction = seq.avg() + seq.sd(); | 2954 avg_prediction = seq.avg() + seq.sd(); |
2888 } | 2955 } |
2889 should_continue = | 2956 |
2890 ( hr != NULL) && | 2957 should_continue = true; |
2891 ( (adaptive_young_list_length()) ? time_remaining_ms > 0.0 | 2958 if (hr == NULL) { |
2892 : _collection_set_size < _young_list_fixed_length ); | 2959 // No need for an ergo verbose message here, |
2960 // getNextMarkRegion() does this when it returns NULL. | |
2961 should_continue = false; | |
2962 } else { | |
2963 if (adaptive_young_list_length()) { | |
2964 if (time_remaining_ms < 0.0) { | |
2965 ergo_verbose1(ErgoCSetConstruction, | |
2966 "stop adding old regions to CSet", | |
2967 ergo_format_reason("remaining time is lower than 0") | |
2968 ergo_format_ms("remaining time"), | |
2969 time_remaining_ms); | |
2970 should_continue = false; | |
2971 } | |
2972 } else { | |
2973 if (_collection_set_size < _young_list_fixed_length) { | |
2974 ergo_verbose2(ErgoCSetConstruction, | |
2975 "stop adding old regions to CSet", | |
2976 ergo_format_reason("CSet length lower than target") | |
2977 ergo_format_region("CSet") | |
2978 ergo_format_region("young target"), | |
2979 _collection_set_size, _young_list_fixed_length); | |
2980 should_continue = false; | |
2981 } | |
2982 } | |
2983 } | |
2893 } while (should_continue); | 2984 } while (should_continue); |
2894 | 2985 |
2895 if (!adaptive_young_list_length() && | 2986 if (!adaptive_young_list_length() && |
2896 _collection_set_size < _young_list_fixed_length) | 2987 _collection_set_size < _young_list_fixed_length) { |
2988 ergo_verbose2(ErgoCSetConstruction, | |
2989 "request partially-young GCs end", | |
2990 ergo_format_reason("CSet length lower than target") | |
2991 ergo_format_region("CSet") | |
2992 ergo_format_region("young target"), | |
2993 _collection_set_size, _young_list_fixed_length); | |
2897 _should_revert_to_full_young_gcs = true; | 2994 _should_revert_to_full_young_gcs = true; |
2995 } | |
2996 | |
2997 old_region_num = _collection_set_size - prev_collection_set_size; | |
2998 | |
2999 ergo_verbose2(ErgoCSetConstruction | ErgoHigh, | |
3000 "add old regions to CSet", | |
3001 ergo_format_region("old") | |
3002 ergo_format_ms("predicted old region time"), | |
3003 old_region_num, | |
3004 predicted_pause_time_ms - prev_predicted_pause_time_ms); | |
2898 } | 3005 } |
2899 | 3006 |
2900 stop_incremental_cset_building(); | 3007 stop_incremental_cset_building(); |
2901 | 3008 |
2902 count_CS_bytes_used(); | 3009 count_CS_bytes_used(); |
2903 | 3010 |
2904 end_recording_regions(); | 3011 end_recording_regions(); |
3012 | |
3013 ergo_verbose5(ErgoCSetConstruction, | |
3014 "finish choosing CSet", | |
3015 ergo_format_region("eden") | |
3016 ergo_format_region("survivors") | |
3017 ergo_format_region("old") | |
3018 ergo_format_ms("predicted pause time") | |
3019 ergo_format_ms("target pause time"), | |
3020 eden_region_num, survivor_region_num, old_region_num, | |
3021 predicted_pause_time_ms, target_pause_time_ms); | |
2905 | 3022 |
2906 double non_young_end_time_sec = os::elapsedTime(); | 3023 double non_young_end_time_sec = os::elapsedTime(); |
2907 _recorded_non_young_cset_choice_time_ms = | 3024 _recorded_non_young_cset_choice_time_ms = |
2908 (non_young_end_time_sec - non_young_start_time_sec) * 1000.0; | 3025 (non_young_end_time_sec - non_young_start_time_sec) * 1000.0; |
2909 } | 3026 } |
2910 | 3027 |
2911 void G1CollectorPolicy_BestRegionsFirst::record_full_collection_end() { | 3028 void G1CollectorPolicy_BestRegionsFirst::record_full_collection_end() { |
2912 G1CollectorPolicy::record_full_collection_end(); | 3029 G1CollectorPolicy::record_full_collection_end(); |
2913 _collectionSetChooser->updateAfterFullCollection(); | 3030 _collectionSetChooser->updateAfterFullCollection(); |
2914 } | |
2915 | |
2916 void G1CollectorPolicy_BestRegionsFirst:: | |
2917 expand_if_possible(size_t numRegions) { | |
2918 size_t expansion_bytes = numRegions * HeapRegion::GrainBytes; | |
2919 _g1->expand(expansion_bytes); | |
2920 } | 3031 } |
2921 | 3032 |
2922 void G1CollectorPolicy_BestRegionsFirst:: | 3033 void G1CollectorPolicy_BestRegionsFirst:: |
2923 record_collection_pause_end() { | 3034 record_collection_pause_end() { |
2924 G1CollectorPolicy::record_collection_pause_end(); | 3035 G1CollectorPolicy::record_collection_pause_end(); |