< prev index next >

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

Print this page
rev 52448 : JDK-8212657: Implementation of JDK-8204089 Promptly Return Unused Committed Memory from G1
Summary: Issue optional, default enabled, concurrent cycles when the VM is idle to reclaim unused internal and Java heap memory.
Reviewed-by:
Contributed-by: Rodrigo Bruno <rbruno@gsd.inesc-id.pt>, Ruslan Synytsky <rs@jelastic.com>, Thomas Schatzl <thomas.schatzl@oracle.com>

@@ -712,24 +712,38 @@
   if (this_pause_included_initial_mark) {
     collector_state()->set_mark_or_rebuild_in_progress(true);
   }
 
   _free_regions_at_end_of_collection = _g1h->num_free_regions();
+
+  update_rs_lengths_prediction();
+
+  // Do not update dynamic IHOP due to G1 periodic collection as it is highly likely
+  // that in this case we are not running in a "normal" operating mode.
+  if (_g1h->gc_cause() != GCCause::_g1_periodic_collection) {
   // IHOP control wants to know the expected young gen length if it were not
   // restrained by the heap reserve. Using the actual length would make the
   // prediction too small and the limit the young gen every time we get to the
   // predicted target occupancy.
   size_t last_unrestrained_young_length = update_young_list_max_and_target_length();
-  update_rs_lengths_prediction();
 
   update_ihop_prediction(app_time_ms / 1000.0,
                          _bytes_allocated_in_old_since_last_gc,
                          last_unrestrained_young_length * HeapRegion::GrainBytes,
                          this_pause_was_young_only);
   _bytes_allocated_in_old_since_last_gc = 0;
 
   _ihop_control->send_trace_event(_g1h->gc_tracer_stw());
+  } else {
+    // Any garbage collection triggered as periodic collection resets the time-to-mixed
+    // measurement. Periodic collection typically means that the application is "inactive", i.e.
+    // the marking threads may have received an uncharacterisic amount of cpu time
+    // for completing the marking, i.e. are faster than expected.
+    // This skews the predicted marking length towards smaller values which might cause
+    // the mark start being too late.
+    _initial_mark_to_mixed.reset();
+  }
 
   // Note that _mmu_tracker->max_gc_time() returns the time in seconds.
   double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0;
 
   if (update_rs_time_goal_ms < scan_hcc_time_ms) {

@@ -1076,11 +1090,13 @@
     case YoungOnlyGC:
     case LastYoungGC:
       _initial_mark_to_mixed.add_pause(end - start);
       break;
     case InitialMarkGC:
+      if (_g1h->gc_cause() != GCCause::_g1_periodic_collection) {
       _initial_mark_to_mixed.record_initial_mark_end(end);
+      }
       break;
     case MixedGC:
       _initial_mark_to_mixed.record_mixed_gc_start(start);
       break;
     default:
< prev index next >