comparison src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @ 1656:4e5661ba9d98

6944166: G1: explicit GCs are not always handled correctly Summary: G1 was not handling explicit GCs correctly in many ways. It does now. See the CR for the list of improvements contained in this changeset. Reviewed-by: iveresov, ysr, johnc
author tonyp
date Mon, 28 Jun 2010 14:13:17 -0400
parents 215576b54709
children 2d160770d2e5
comparison
equal deleted inserted replaced
1655:e7ec8cd4dd8a 1656:4e5661ba9d98
152 152
153 _known_garbage_ratio(0.0), 153 _known_garbage_ratio(0.0),
154 _known_garbage_bytes(0), 154 _known_garbage_bytes(0),
155 155
156 _young_gc_eff_seq(new TruncatedSeq(TruncatedSeqLength)), 156 _young_gc_eff_seq(new TruncatedSeq(TruncatedSeqLength)),
157 _target_pause_time_ms(-1.0),
158 157
159 _recent_prev_end_times_for_all_gcs_sec(new TruncatedSeq(NumPrevPausesForHeuristics)), 158 _recent_prev_end_times_for_all_gcs_sec(new TruncatedSeq(NumPrevPausesForHeuristics)),
160 159
161 _recent_CS_bytes_used_before(new TruncatedSeq(NumPrevPausesForHeuristics)), 160 _recent_CS_bytes_used_before(new TruncatedSeq(NumPrevPausesForHeuristics)),
162 _recent_CS_bytes_surviving(new TruncatedSeq(NumPrevPausesForHeuristics)), 161 _recent_CS_bytes_surviving(new TruncatedSeq(NumPrevPausesForHeuristics)),
1633 1632
1634 // Note that _mmu_tracker->max_gc_time() returns the time in seconds. 1633 // Note that _mmu_tracker->max_gc_time() returns the time in seconds.
1635 double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0; 1634 double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0;
1636 adjust_concurrent_refinement(update_rs_time, update_rs_processed_buffers, update_rs_time_goal_ms); 1635 adjust_concurrent_refinement(update_rs_time, update_rs_processed_buffers, update_rs_time_goal_ms);
1637 // </NEW PREDICTION> 1636 // </NEW PREDICTION>
1638
1639 _target_pause_time_ms = -1.0;
1640 } 1637 }
1641 1638
1642 // <NEW PREDICTION> 1639 // <NEW PREDICTION>
1643 1640
1644 void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time, 1641 void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time,
2364 2361
2365 if (in_young_gc_mode()) { 2362 if (in_young_gc_mode()) {
2366 if (reached_target_length) { 2363 if (reached_target_length) {
2367 assert( young_list_length > 0 && _g1->young_list()->length() > 0, 2364 assert( young_list_length > 0 && _g1->young_list()->length() > 0,
2368 "invariant" ); 2365 "invariant" );
2369 _target_pause_time_ms = max_pause_time_ms;
2370 return true; 2366 return true;
2371 } 2367 }
2372 } else { 2368 } else {
2373 guarantee( false, "should not reach here" ); 2369 guarantee( false, "should not reach here" );
2374 } 2370 }
2395 HRSortIndexIsOKClosure cl(_collectionSetChooser); 2391 HRSortIndexIsOKClosure cl(_collectionSetChooser);
2396 _g1->heap_region_iterate(&cl); 2392 _g1->heap_region_iterate(&cl);
2397 return true; 2393 return true;
2398 } 2394 }
2399 #endif 2395 #endif
2396
2397 bool
2398 G1CollectorPolicy::force_initial_mark_if_outside_cycle() {
2399 bool during_cycle = _g1->concurrent_mark()->cmThread()->during_cycle();
2400 if (!during_cycle) {
2401 set_initiate_conc_mark_if_possible();
2402 return true;
2403 } else {
2404 return false;
2405 }
2406 }
2400 2407
2401 void 2408 void
2402 G1CollectorPolicy::decide_on_conc_mark_initiation() { 2409 G1CollectorPolicy::decide_on_conc_mark_initiation() {
2403 // We are about to decide on whether this pause will be an 2410 // We are about to decide on whether this pause will be an
2404 // initial-mark pause. 2411 // initial-mark pause.
2862 } 2869 }
2863 } 2870 }
2864 #endif // !PRODUCT 2871 #endif // !PRODUCT
2865 2872
2866 bool 2873 bool
2867 G1CollectorPolicy_BestRegionsFirst::choose_collection_set() { 2874 G1CollectorPolicy_BestRegionsFirst::choose_collection_set(
2875 double target_pause_time_ms) {
2868 // Set this here - in case we're not doing young collections. 2876 // Set this here - in case we're not doing young collections.
2869 double non_young_start_time_sec = os::elapsedTime(); 2877 double non_young_start_time_sec = os::elapsedTime();
2870 2878
2871 // The result that this routine will return. This will be set to 2879 // The result that this routine will return. This will be set to
2872 // false if: 2880 // false if:
2875 // * we add old regions to the collection set. 2883 // * we add old regions to the collection set.
2876 bool abandon_collection = true; 2884 bool abandon_collection = true;
2877 2885
2878 start_recording_regions(); 2886 start_recording_regions();
2879 2887
2880 guarantee(_target_pause_time_ms > -1.0 2888 guarantee(target_pause_time_ms > 0.0,
2881 NOT_PRODUCT(|| Universe::heap()->gc_cause() == GCCause::_scavenge_alot), 2889 err_msg("target_pause_time_ms = %1.6lf should be positive",
2882 "_target_pause_time_ms should have been set!"); 2890 target_pause_time_ms));
2883 #ifndef PRODUCT 2891 guarantee(_collection_set == NULL, "Precondition");
2884 if (_target_pause_time_ms <= -1.0) {
2885 assert(ScavengeALot && Universe::heap()->gc_cause() == GCCause::_scavenge_alot, "Error");
2886 _target_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0;
2887 }
2888 #endif
2889 assert(_collection_set == NULL, "Precondition");
2890 2892
2891 double base_time_ms = predict_base_elapsed_time_ms(_pending_cards); 2893 double base_time_ms = predict_base_elapsed_time_ms(_pending_cards);
2892 double predicted_pause_time_ms = base_time_ms; 2894 double predicted_pause_time_ms = base_time_ms;
2893 2895
2894 double target_time_ms = _target_pause_time_ms; 2896 double time_remaining_ms = target_pause_time_ms - base_time_ms;
2895 double time_remaining_ms = target_time_ms - base_time_ms;
2896 2897
2897 // the 10% and 50% values are arbitrary... 2898 // the 10% and 50% values are arbitrary...
2898 if (time_remaining_ms < 0.10*target_time_ms) { 2899 if (time_remaining_ms < 0.10 * target_pause_time_ms) {
2899 time_remaining_ms = 0.50 * target_time_ms; 2900 time_remaining_ms = 0.50 * target_pause_time_ms;
2900 _within_target = false; 2901 _within_target = false;
2901 } else { 2902 } else {
2902 _within_target = true; 2903 _within_target = true;
2903 } 2904 }
2904 2905
3057 3058
3058 double non_young_end_time_sec = os::elapsedTime(); 3059 double non_young_end_time_sec = os::elapsedTime();
3059 _recorded_non_young_cset_choice_time_ms = 3060 _recorded_non_young_cset_choice_time_ms =
3060 (non_young_end_time_sec - non_young_start_time_sec) * 1000.0; 3061 (non_young_end_time_sec - non_young_start_time_sec) * 1000.0;
3061 3062
3062 return abandon_collection; 3063 // Here we are supposed to return whether the pause should be
3064 // abandoned or not (i.e., whether the collection set is empty or
3065 // not). However, this introduces a subtle issue when a pause is
3066 // initiated explicitly with System.gc() and
3067 // +ExplicitGCInvokesConcurrent (see Comment #2 in CR 6944166), it's
3068 // supposed to start a marking cycle, and it's abandoned. So, by
3069 // returning false here we are telling the caller never to consider
3070 // a pause to be abandoned. We'll actually remove all the code
3071 // associated with abandoned pauses as part of CR 6963209, but we are
3072 // just disabling them this way for the moment to avoid increasing
3073 // further the amount of changes for CR 6944166.
3074 return false;
3063 } 3075 }
3064 3076
3065 void G1CollectorPolicy_BestRegionsFirst::record_full_collection_end() { 3077 void G1CollectorPolicy_BestRegionsFirst::record_full_collection_end() {
3066 G1CollectorPolicy::record_full_collection_end(); 3078 G1CollectorPolicy::record_full_collection_end();
3067 _collectionSetChooser->updateAfterFullCollection(); 3079 _collectionSetChooser->updateAfterFullCollection();