src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp

changeset 980
58054a18d735
parent 961
818efdefcc99
child 982
1e458753107d
     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) {

mercurial