< prev index next >

src/hotspot/share/gc/g1/g1Policy.cpp

Print this page
rev 57223 : imported patch 8225484-changes-to-survivor-calculation

@@ -61,11 +61,12 @@
   _collection_pause_end_millis(os::javaTimeNanos() / NANOSECS_PER_MILLISEC),
   _young_list_target_length(0),
   _young_list_fixed_length(0),
   _young_list_max_length(0),
   _eden_surv_rate_group(new G1SurvRateGroup()),
-  _survivor_surv_rate_group(new G1SurvRateGroup()),
+  _survivor_used_bytes_at_start(0),
+  _survivor_used_bytes_at_end(0),
   _reserve_factor((double) G1ReservePercent / 100.0),
   _reserve_regions(0),
   _young_gen_sizer(G1YoungGenSizer::create_gen_sizer()),
   _free_regions_at_end_of_collection(0),
   _rs_length(0),

@@ -82,11 +83,11 @@
   _phase_times(new G1GCPhaseTimes(gc_timer, ParallelGCThreads)),
   _mark_remark_start_sec(0),
   _mark_cleanup_start_sec(0),
   _tenuring_threshold(MaxTenuringThreshold),
   _max_survivor_regions(0),
-  _survivors_age_table(true)
+  _surviving_survivor_words(0)
 {
 }
 
 G1Policy::~G1Policy() {
   delete _ihop_control;

@@ -396,10 +397,13 @@
   double survivor_regions_evac_time = 0.0;
   const GrowableArray<HeapRegion*>* survivor_regions = _g1h->survivor()->regions();
   for (GrowableArrayIterator<HeapRegion*> it = survivor_regions->begin();
        it != survivor_regions->end();
        ++it) {
+    // We could split out copy_time from total time here and calculate it based on
+    // the number of survivor regions. Since we need to iterate over the regions
+    // for the non_copy time anyway, keep it.
     survivor_regions_evac_time += predict_region_total_time_ms(*it, collector_state()->in_young_only_phase());
   }
   return survivor_regions_evac_time;
 }
 

@@ -453,14 +457,12 @@
   collector_state()->set_in_initial_mark_gc(false);
   collector_state()->set_mark_or_rebuild_in_progress(false);
   collector_state()->set_clearing_next_bitmap(false);
 
   _eden_surv_rate_group->start_adding_regions();
-  // also call this on any additional surv rate groups
 
   _free_regions_at_end_of_collection = _g1h->num_free_regions();
-  _survivor_surv_rate_group->reset();
   update_young_list_max_and_target_length();
   update_rs_length_prediction();
   _pending_cards_at_prev_gc_end = _g1h->pending_card_num();
 
   _bytes_allocated_in_old_since_last_gc = 0;

@@ -525,10 +527,12 @@
 void G1Policy::record_collection_pause_start(double start_time_sec) {
   // We only need to do this here as the policy will only be applied
   // to the GC we're about to start. so, no point is calculating this
   // every time we calculate / recalculate the target young length.
   update_survivors_policy();
+  _survivor_used_bytes_at_start = _g1h->survivor()->used_bytes();
+  _survivor_used_bytes_at_end = 0;
 
   assert(max_survivor_regions() + _g1h->num_used_regions() <= _g1h->max_regions(),
          "Maximum survivor regions %u plus used regions %u exceeds max regions %u",
          max_survivor_regions(), _g1h->num_used_regions(), _g1h->max_regions());
   assert_used_and_recalculate_used_equal(_g1h);

@@ -540,10 +544,11 @@
   _collection_set->reset_bytes_used_before();
 
   // do that for any other surv rate groups
   _eden_surv_rate_group->stop_adding_regions();
   _survivors_age_table.clear();
+  _surviving_survivor_words = 0;
 
   assert(_g1h->collection_set()->verify_young_ages(), "region age verification failed");
 }
 
 void G1Policy::record_concurrent_mark_init_end(double mark_init_elapsed_time_ms) {

@@ -650,10 +655,21 @@
     record_concurrent_mark_init_end(0.0);
   } else {
     maybe_start_marking();
   }
 
+  size_t survived = _surviving_survivor_words * HeapWordSize;
+
+  if (_survivor_used_bytes_at_start != 0) {
+    double ratio = (double)survived / _survivor_used_bytes_at_start;
+    guarantee(ratio >= 0.0 && ratio <= 1.0, "ratio %.3lf", ratio);
+    _analytics->report_survivor_ratio(ratio);
+  } else {
+    _analytics->report_survivor_ratio(0.0f);
+  }
+  _survivor_used_bytes_at_end = survived;
+  
   double app_time_ms = (phase_times()->cur_collection_start_sec() * 1000.0 - _analytics->prev_collection_pause_end_ms());
   if (app_time_ms < MIN_TIMER_GRANULARITY) {
     // This usually happens due to the timer not having the required
     // granularity. Some Linuxes are the usual culprits.
     // We'll just set it to something (arbitrarily) small.

@@ -912,15 +928,30 @@
   size_t rs_length = _analytics->predict_rs_length();
   return predict_base_elapsed_time_ms(pending_cards, rs_length);
 }
 
 size_t G1Policy::predict_bytes_to_copy(HeapRegion* hr) const {
-  size_t bytes_to_copy;
+  size_t bytes_to_copy = 0;
   if (!hr->is_young()) {
     bytes_to_copy = hr->max_live_bytes();
   } else {
-    bytes_to_copy = (size_t) (hr->used() * hr->surv_rate_prediction(_predictor));
+    size_t survived = hr->survivor_bytes();
+
+    guarantee(hr->used() >= survived, "Used " SIZE_FORMAT " >= survived " SIZE_FORMAT, hr->used(), survived);
+
+    if (survived > 0) {
+      bytes_to_copy += survived * _analytics->predict_survivor_ratio();
+    }
+
+    if (hr->used() > survived) {
+      bytes_to_copy += (size_t) ((hr->used() - survived) * hr->surv_rate_prediction(_predictor));
+    }
+    /*
+    log_debug(gc)("straggler region %u type %s old survived " SIZE_FORMAT " exp survived " SIZE_FORMAT " eden used " SIZE_FORMAT " exp eden survived " SIZE_FORMAT " total " SIZE_FORMAT,
+                  hr->hrm_index(), hr->get_short_type_str(), survived, (size_t)(survived * _analytics->predict_survivor_ratio()), hr->used() - survived,
+                  ((hr->used() - survived) > 0) ? (size_t)((hr->used() - survived) * hr->surv_rate_prediction(_predictor)) : 0, bytes_to_copy);
+     */
   }
   return bytes_to_copy;
 }
 
 double G1Policy::predict_eden_copy_time_ms(uint count, size_t* bytes_to_copy) const {

@@ -1386,27 +1417,23 @@
   log_debug(gc, ergo, cset)("Prepared %u regions out of %u for optional evacuation. Predicted time: %.3fms",
                             num_optional_regions, max_optional_regions, prediction_ms);
 }
 
 void G1Policy::transfer_survivors_to_cset(const G1SurvivorRegions* survivors) {
-  note_start_adding_survivor_regions();
-
   HeapRegion* last = NULL;
   for (GrowableArrayIterator<HeapRegion*> it = survivors->regions()->begin();
        it != survivors->regions()->end();
        ++it) {
     HeapRegion* curr = *it;
-    set_region_survivor(curr);
 
     // The region is a non-empty survivor so let's add it to
     // the incremental collection set for the next evacuation
     // pause.
     _collection_set->add_survivor_regions(curr);
 
     last = curr;
   }
-  note_stop_adding_survivor_regions();
 
   // Don't clear the survivor list handles until the start of
   // the next evacuation pause - we need it in order to re-tag
   // the survivor regions from this evacuation pause as 'young'
   // at the start of the next.
< prev index next >