1.1 --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Thu Feb 05 11:42:10 2009 -0800 1.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Fri Feb 06 01:38:50 2009 +0300 1.3 @@ -196,8 +196,13 @@ 1.4 _short_lived_surv_rate_group(new SurvRateGroup(this, "Short Lived", 1.5 G1YoungSurvRateNumRegionsSummary)), 1.6 _survivor_surv_rate_group(new SurvRateGroup(this, "Survivor", 1.7 - G1YoungSurvRateNumRegionsSummary)) 1.8 + G1YoungSurvRateNumRegionsSummary)), 1.9 // add here any more surv rate groups 1.10 + _recorded_survivor_regions(0), 1.11 + _recorded_survivor_head(NULL), 1.12 + _recorded_survivor_tail(NULL), 1.13 + _survivors_age_table(true) 1.14 + 1.15 { 1.16 _recent_prev_end_times_for_all_gcs_sec->add(os::elapsedTime()); 1.17 _prev_collection_pause_end_ms = os::elapsedTime() * 1000.0; 1.18 @@ -272,6 +277,15 @@ 1.19 _concurrent_mark_cleanup_times_ms->add(0.20); 1.20 _tenuring_threshold = MaxTenuringThreshold; 1.21 1.22 + if (G1UseSurvivorSpace) { 1.23 + // if G1FixedSurvivorSpaceSize is 0 which means the size is not 1.24 + // fixed, then _max_survivor_regions will be calculated at 1.25 + // calculate_young_list_target_config diring initialization 1.26 + _max_survivor_regions = G1FixedSurvivorSpaceSize / HeapRegion::GrainBytes; 1.27 + } else { 1.28 + _max_survivor_regions = 0; 1.29 + } 1.30 + 1.31 initialize_all(); 1.32 } 1.33 1.34 @@ -301,6 +315,8 @@ 1.35 "-XX:+UseConcMarkSweepGC."); 1.36 } 1.37 1.38 + initialize_gc_policy_counters(); 1.39 + 1.40 if (G1Gen) { 1.41 _in_young_gc_mode = true; 1.42 1.43 @@ -322,6 +338,12 @@ 1.44 } 1.45 } 1.46 1.47 +// Create the jstat counters for the policy. 1.48 +void G1CollectorPolicy::initialize_gc_policy_counters() 1.49 +{ 1.50 + _gc_policy_counters = new GCPolicyCounters("GarbageFirst", 1, 2 + G1Gen); 1.51 +} 1.52 + 1.53 void G1CollectorPolicy::calculate_young_list_min_length() { 1.54 _young_list_min_length = 0; 1.55 1.56 @@ -352,6 +374,7 @@ 1.57 guarantee( so_length < _young_list_target_length, "invariant" ); 1.58 _young_list_so_prefix_length = so_length; 1.59 } 1.60 + calculate_survivors_policy(); 1.61 } 1.62 1.63 // This method calculate the optimal scan-only set for a fixed young 1.64 @@ -448,6 +471,9 @@ 1.65 if (full_young_gcs() && _free_regions_at_end_of_collection > 0) { 1.66 // we are in fully-young mode and there are free regions in the heap 1.67 1.68 + double survivor_regions_evac_time = 1.69 + predict_survivor_regions_evac_time(); 1.70 + 1.71 size_t min_so_length = 0; 1.72 size_t max_so_length = 0; 1.73 1.74 @@ -497,9 +523,8 @@ 1.75 scanned_cards = predict_non_young_card_num(adj_rs_lengths); 1.76 // calculate this once, so that we don't have to recalculate it in 1.77 // the innermost loop 1.78 - double base_time_ms = predict_base_elapsed_time_ms(pending_cards, 1.79 - scanned_cards); 1.80 - 1.81 + double base_time_ms = predict_base_elapsed_time_ms(pending_cards, scanned_cards) 1.82 + + survivor_regions_evac_time; 1.83 // the result 1.84 size_t final_young_length = 0; 1.85 size_t final_so_length = 0; 1.86 @@ -548,14 +573,14 @@ 1.87 bool done = false; 1.88 // this is the outermost loop 1.89 while (!done) { 1.90 -#if 0 1.91 +#ifdef TRACE_CALC_YOUNG_CONFIG 1.92 // leave this in for debugging, just in case 1.93 gclog_or_tty->print_cr("searching between " SIZE_FORMAT " and " SIZE_FORMAT 1.94 ", incr " SIZE_FORMAT ", pass %s", 1.95 from_so_length, to_so_length, so_length_incr, 1.96 (pass == pass_type_coarse) ? "coarse" : 1.97 (pass == pass_type_fine) ? "fine" : "final"); 1.98 -#endif // 0 1.99 +#endif // TRACE_CALC_YOUNG_CONFIG 1.100 1.101 size_t so_length = from_so_length; 1.102 size_t init_free_regions = 1.103 @@ -651,11 +676,11 @@ 1.104 guarantee( so_length_incr == so_coarse_increments, "invariant" ); 1.105 guarantee( final_so_length >= min_so_length, "invariant" ); 1.106 1.107 -#if 0 1.108 +#ifdef TRACE_CALC_YOUNG_CONFIG 1.109 // leave this in for debugging, just in case 1.110 gclog_or_tty->print_cr(" coarse pass: SO length " SIZE_FORMAT, 1.111 final_so_length); 1.112 -#endif // 0 1.113 +#endif // TRACE_CALC_YOUNG_CONFIG 1.114 1.115 from_so_length = 1.116 (final_so_length - min_so_length > so_coarse_increments) ? 1.117 @@ -687,12 +712,12 @@ 1.118 // of the optimal 1.119 size_t new_so_length = 950 * final_so_length / 1000; 1.120 1.121 -#if 0 1.122 +#ifdef TRACE_CALC_YOUNG_CONFIG 1.123 // leave this in for debugging, just in case 1.124 gclog_or_tty->print_cr(" fine pass: SO length " SIZE_FORMAT 1.125 ", setting it to " SIZE_FORMAT, 1.126 final_so_length, new_so_length); 1.127 -#endif // 0 1.128 +#endif // TRACE_CALC_YOUNG_CONFIG 1.129 1.130 from_so_length = new_so_length; 1.131 to_so_length = new_so_length; 1.132 @@ -719,7 +744,8 @@ 1.133 } 1.134 1.135 // we should have at least one region in the target young length 1.136 - _young_list_target_length = MAX2((size_t) 1, final_young_length); 1.137 + _young_list_target_length = 1.138 + MAX2((size_t) 1, final_young_length + _recorded_survivor_regions); 1.139 if (final_so_length >= final_young_length) 1.140 // and we need to ensure that the S-O length is not greater than 1.141 // the target young length (this is being a bit careful) 1.142 @@ -734,7 +760,7 @@ 1.143 double end_time_sec = os::elapsedTime(); 1.144 double elapsed_time_ms = (end_time_sec - start_time_sec) * 1000.0; 1.145 1.146 -#if 0 1.147 +#ifdef TRACE_CALC_YOUNG_CONFIG 1.148 // leave this in for debugging, just in case 1.149 gclog_or_tty->print_cr("target = %1.1lf ms, young = " SIZE_FORMAT 1.150 ", SO = " SIZE_FORMAT ", " 1.151 @@ -747,9 +773,9 @@ 1.152 calculations, 1.153 full_young_gcs() ? "full" : "partial", 1.154 should_initiate_conc_mark() ? " i-m" : "", 1.155 - in_marking_window(), 1.156 - in_marking_window_im()); 1.157 -#endif // 0 1.158 + _in_marking_window, 1.159 + _in_marking_window_im); 1.160 +#endif // TRACE_CALC_YOUNG_CONFIG 1.161 1.162 if (_young_list_target_length < _young_list_min_length) { 1.163 // bummer; this means that, if we do a pause when the optimal 1.164 @@ -768,14 +794,14 @@ 1.165 // S-O length 1.166 so_length = calculate_optimal_so_length(_young_list_min_length); 1.167 1.168 -#if 0 1.169 +#ifdef TRACE_CALC_YOUNG_CONFIG 1.170 // leave this in for debugging, just in case 1.171 gclog_or_tty->print_cr("adjusted target length from " 1.172 SIZE_FORMAT " to " SIZE_FORMAT 1.173 ", SO " SIZE_FORMAT, 1.174 _young_list_target_length, _young_list_min_length, 1.175 so_length); 1.176 -#endif // 0 1.177 +#endif // TRACE_CALC_YOUNG_CONFIG 1.178 1.179 _young_list_target_length = 1.180 MAX2(_young_list_min_length, (size_t)1); 1.181 @@ -785,12 +811,12 @@ 1.182 // we are in a partially-young mode or we've run out of regions (due 1.183 // to evacuation failure) 1.184 1.185 -#if 0 1.186 +#ifdef TRACE_CALC_YOUNG_CONFIG 1.187 // leave this in for debugging, just in case 1.188 gclog_or_tty->print_cr("(partial) setting target to " SIZE_FORMAT 1.189 ", SO " SIZE_FORMAT, 1.190 _young_list_min_length, 0); 1.191 -#endif // 0 1.192 +#endif // TRACE_CALC_YOUNG_CONFIG 1.193 1.194 // we'll do the pause as soon as possible and with no S-O prefix 1.195 // (see above for the reasons behind the latter) 1.196 @@ -884,6 +910,16 @@ 1.197 return true; 1.198 } 1.199 1.200 +double G1CollectorPolicy::predict_survivor_regions_evac_time() { 1.201 + double survivor_regions_evac_time = 0.0; 1.202 + for (HeapRegion * r = _recorded_survivor_head; 1.203 + r != NULL && r != _recorded_survivor_tail->get_next_young_region(); 1.204 + r = r->get_next_young_region()) { 1.205 + survivor_regions_evac_time += predict_region_elapsed_time_ms(r, true); 1.206 + } 1.207 + return survivor_regions_evac_time; 1.208 +} 1.209 + 1.210 void G1CollectorPolicy::check_prediction_validity() { 1.211 guarantee( adaptive_young_list_length(), "should not call this otherwise" ); 1.212 1.213 @@ -995,11 +1031,15 @@ 1.214 _short_lived_surv_rate_group->start_adding_regions(); 1.215 // also call this on any additional surv rate groups 1.216 1.217 + record_survivor_regions(0, NULL, NULL); 1.218 + 1.219 _prev_region_num_young = _region_num_young; 1.220 _prev_region_num_tenured = _region_num_tenured; 1.221 1.222 _free_regions_at_end_of_collection = _g1->free_regions(); 1.223 _scan_only_regions_at_end_of_collection = 0; 1.224 + // Reset survivors SurvRateGroup. 1.225 + _survivor_surv_rate_group->reset(); 1.226 calculate_young_list_min_length(); 1.227 calculate_young_list_target_config(); 1.228 } 1.229 @@ -1104,6 +1144,10 @@ 1.230 _short_lived_surv_rate_group->record_scan_only_prefix(short_lived_so_length); 1.231 tag_scan_only(short_lived_so_length); 1.232 1.233 + if (G1UseSurvivorSpace) { 1.234 + _survivors_age_table.clear(); 1.235 + } 1.236 + 1.237 assert( verify_young_ages(), "region age verification" ); 1.238 } 1.239 1.240 @@ -1965,9 +2009,6 @@ 1.241 // </NEW PREDICTION> 1.242 1.243 _target_pause_time_ms = -1.0; 1.244 - 1.245 - // TODO: calculate tenuring threshold 1.246 - _tenuring_threshold = MaxTenuringThreshold; 1.247 } 1.248 1.249 // <NEW PREDICTION> 1.250 @@ -2058,7 +2099,7 @@ 1.251 guarantee( hr->is_young() && hr->age_in_surv_rate_group() != -1, 1.252 "invariant" ); 1.253 int age = hr->age_in_surv_rate_group(); 1.254 - double yg_surv_rate = predict_yg_surv_rate(age); 1.255 + double yg_surv_rate = predict_yg_surv_rate(age, hr->surv_rate_group()); 1.256 bytes_to_copy = (size_t) ((double) hr->used() * yg_surv_rate); 1.257 } 1.258 1.259 @@ -2091,7 +2132,7 @@ 1.260 } 1.261 #if PREDICTIONS_VERBOSE 1.262 if (young) { 1.263 - _recorded_young_bytes += hr->asSpace()->used(); 1.264 + _recorded_young_bytes += hr->used(); 1.265 } else { 1.266 _recorded_marked_bytes += hr->max_live_bytes(); 1.267 } 1.268 @@ -2119,11 +2160,6 @@ 1.269 predict_non_young_card_num(_predicted_rs_lengths); 1.270 _recorded_region_num = _recorded_young_regions + _recorded_non_young_regions; 1.271 1.272 - _predicted_young_survival_ratio = 0.0; 1.273 - for (int i = 0; i < _recorded_young_regions; ++i) 1.274 - _predicted_young_survival_ratio += predict_yg_surv_rate(i); 1.275 - _predicted_young_survival_ratio /= (double) _recorded_young_regions; 1.276 - 1.277 _predicted_scan_only_scan_time_ms = 1.278 predict_scan_only_time_ms(_recorded_scan_only_regions); 1.279 _predicted_rs_update_time_ms = 1.280 @@ -2673,8 +2709,11 @@ 1.281 assert(in_young_gc_mode(), "should be in young GC mode"); 1.282 bool ret; 1.283 size_t young_list_length = _g1->young_list_length(); 1.284 - 1.285 - if (young_list_length < _young_list_target_length) { 1.286 + size_t young_list_max_length = _young_list_target_length; 1.287 + if (G1FixedEdenSize) { 1.288 + young_list_max_length -= _max_survivor_regions; 1.289 + } 1.290 + if (young_list_length < young_list_max_length) { 1.291 ret = true; 1.292 ++_region_num_young; 1.293 } else { 1.294 @@ -2710,17 +2749,39 @@ 1.295 } 1.296 1.297 1.298 -uint G1CollectorPolicy::max_regions(int purpose) { 1.299 +size_t G1CollectorPolicy::max_regions(int purpose) { 1.300 switch (purpose) { 1.301 case GCAllocForSurvived: 1.302 - return G1MaxSurvivorRegions; 1.303 + return _max_survivor_regions; 1.304 case GCAllocForTenured: 1.305 - return UINT_MAX; 1.306 + return REGIONS_UNLIMITED; 1.307 default: 1.308 - return UINT_MAX; 1.309 + ShouldNotReachHere(); 1.310 + return REGIONS_UNLIMITED; 1.311 }; 1.312 } 1.313 1.314 +// Calculates survivor space parameters. 1.315 +void G1CollectorPolicy::calculate_survivors_policy() 1.316 +{ 1.317 + if (!G1UseSurvivorSpace) { 1.318 + return; 1.319 + } 1.320 + if (G1FixedSurvivorSpaceSize == 0) { 1.321 + _max_survivor_regions = _young_list_target_length / SurvivorRatio; 1.322 + } else { 1.323 + _max_survivor_regions = G1FixedSurvivorSpaceSize; 1.324 + } 1.325 + 1.326 + if (G1FixedTenuringThreshold) { 1.327 + _tenuring_threshold = MaxTenuringThreshold; 1.328 + } else { 1.329 + _tenuring_threshold = _survivors_age_table.compute_tenuring_threshold( 1.330 + HeapRegion::GrainWords * _max_survivor_regions); 1.331 + } 1.332 +} 1.333 + 1.334 + 1.335 void 1.336 G1CollectorPolicy_BestRegionsFirst:: 1.337 set_single_region_collection_set(HeapRegion* hr) { 1.338 @@ -2743,7 +2804,11 @@ 1.339 double max_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0; 1.340 1.341 size_t young_list_length = _g1->young_list_length(); 1.342 - bool reached_target_length = young_list_length >= _young_list_target_length; 1.343 + size_t young_list_max_length = _young_list_target_length; 1.344 + if (G1FixedEdenSize) { 1.345 + young_list_max_length -= _max_survivor_regions; 1.346 + } 1.347 + bool reached_target_length = young_list_length >= young_list_max_length; 1.348 1.349 if (in_young_gc_mode()) { 1.350 if (reached_target_length) {