changeset 9445:98bc77f54ead

Adding a new Shenandoah heuristic called 'newadaptive'.
author Raoul Veroy <rveroy@cs.tufts.edu>
date Tue, 11 Aug 2015 17:02:16 -0400
parents 4a1d26f20b62
children ea0fa7eace6e
files src/share/vm/gc_implementation/shenandoah/shenandoahCollectorPolicy.cpp src/share/vm/gc_implementation/shenandoah/shenandoahCollectorPolicy.hpp src/share/vm/gc_implementation/shenandoah/shenandoahHeap.cpp src/share/vm/gc_implementation/shenandoah/shenandoahHeap.hpp src/share/vm/runtime/globals.hpp
diffstat 5 files changed, 145 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/gc_implementation/shenandoah/shenandoahCollectorPolicy.cpp	Tue Aug 11 13:01:06 2015 +0200
+++ b/src/share/vm/gc_implementation/shenandoah/shenandoahCollectorPolicy.cpp	Tue Aug 11 17:02:16 2015 -0400
@@ -9,12 +9,18 @@
   size_t _bytes_allocated_since_CM;
   size_t _bytes_reclaimed_this_cycle;
 
+protected:
+  size_t _bytes_allocated_start_CM;
+  size_t _bytes_allocated_during_CM;
+
 public:
 
   ShenandoahHeuristics();
 
   void record_bytes_allocated(size_t bytes);
   void record_bytes_reclaimed(size_t bytes);
+  void record_bytes_start_CM(size_t bytes);
+  void record_bytes_end_CM(size_t bytes);
 
   virtual bool should_start_concurrent_mark(size_t used, size_t capacity) const=0;
   virtual bool update_refs_early();
@@ -26,7 +32,9 @@
 
 ShenandoahHeuristics::ShenandoahHeuristics() :
   _bytes_allocated_since_CM(0),
-  _bytes_reclaimed_this_cycle(0)
+  _bytes_reclaimed_this_cycle(0),
+  _bytes_allocated_start_CM(0),
+  _bytes_allocated_during_CM(0)
 {
   if (PrintGCDetails)
     tty->print_cr("initializing heuristics");
@@ -81,15 +89,18 @@
     //    assert(heap->calculateUsed() == heap->used(), "Stashed heap used must be equal to calculated heap used");
     gclog_or_tty->print_cr("]");
 
-    if (phase == recycle_regions)
+    if (phase == recycle_regions) {
       _tracer->report_gc_end(_conc_timer->gc_end(), _conc_timer->time_partitions());
-    else if (phase == full_gc)
+    } else if (phase == full_gc) {
       _tracer->report_gc_end(_stw_timer->gc_end(), _stw_timer->time_partitions());
-    else if (phase == conc_mark || phase == conc_evac || phase == conc_uprefs || phase == prepare_evac) {
+    } else if (phase == conc_mark || phase == conc_evac || phase == conc_uprefs || phase == prepare_evac) {
       if (_conc_gc_aborted) {
-	_tracer->report_gc_end(_conc_timer->gc_end(), _conc_timer->time_partitions());
-	clear_conc_gc_aborted();
+        _tracer->report_gc_end(_conc_timer->gc_end(), _conc_timer->time_partitions());
+        clear_conc_gc_aborted();
       }
+    } else if (phase == final_evac) {
+      ShenandoahHeap* heap = ShenandoahHeap::heap();
+      this->record_bytes_end_CM(heap->_bytesAllocSinceCM);
     }
   }
 }
@@ -108,6 +119,7 @@
 
 void ShenandoahHeuristics::record_bytes_allocated(size_t bytes) {
   _bytes_allocated_since_CM = bytes;
+  _bytes_allocated_start_CM = bytes;
   _allocation_rate_bytes.add(bytes);
 }
 
@@ -116,6 +128,15 @@
   _reclamation_rate_bytes.add(bytes);
 }
 
+void ShenandoahHeuristics::record_bytes_start_CM(size_t bytes) {
+  _bytes_allocated_start_CM = bytes;
+}
+
+void ShenandoahHeuristics::record_bytes_end_CM(size_t bytes) {
+  _bytes_allocated_during_CM = (bytes > _bytes_allocated_start_CM) ? (bytes - _bytes_allocated_start_CM)
+                                                                   : bytes;
+}
+
 class AggressiveHeuristics : public ShenandoahHeuristics {
 public:
   AggressiveHeuristics() : ShenandoahHeuristics(){
@@ -411,6 +432,87 @@
   }
 };
 
+class NewAdaptiveHeuristics : public ShenandoahHeuristics {
+private:
+  size_t _max_live_data;
+  double _target_heap_occupancy_factor;
+  double _allocation_threshold_factor;
+  size_t _last_bytesAllocSinceCM;
+
+  uintx _target_heap_occupancy;
+  uintx _allocation_threshold;
+
+public:
+  NewAdaptiveHeuristics() : ShenandoahHeuristics()
+  {
+    if (PrintGCDetails) {
+      tty->print_cr("Initializing newadaptive heuristics");
+    }
+    _max_live_data = 0;
+    _allocation_threshold = 0;
+    _target_heap_occupancy_factor = 0.;
+    _allocation_threshold_factor = 0.;
+    _last_bytesAllocSinceCM = 0;
+  }
+
+  virtual ~NewAdaptiveHeuristics() {}
+
+  virtual bool should_start_concurrent_mark(size_t used, size_t capacity) const
+  {
+      if (this->_bytes_allocated_during_CM > 0) {
+          // Not the first concurrent mark.
+          // _bytes_allocated_during_CM
+          ShenandoahHeap *heap = ShenandoahHeap::heap();
+          size_t threshold_bytes_allocated = heap->capacity() / 4;
+          size_t targetStartMarking = (size_t) capacity * this->_target_heap_occupancy_factor;
+          return (used > targetStartMarking) && (this->_bytes_allocated_during_CM > threshold_bytes_allocated);
+      } else {
+          // First concurrent mark.
+          size_t targetStartMarking = capacity / 2;
+          ShenandoahHeap *heap = ShenandoahHeap::heap();
+          size_t threshold_bytes_allocated = heap->capacity() / 4;
+
+          // Need to check that an appropriate number of regions have
+          // been allocated since last concurrent mark too.
+          return (used > targetStartMarking) && (heap->_bytesAllocSinceCM > threshold_bytes_allocated);
+      }
+  }
+
+  virtual void choose_collection_and_free_sets(ShenandoahHeapRegionSet* region_set,
+                                               ShenandoahHeapRegionSet* collection_set,
+                                               ShenandoahHeapRegionSet* free_set)
+  {
+    ShenandoahHeap *_heap = ShenandoahHeap::heap();
+    this->_last_bytesAllocSinceCM = ShenandoahHeap::heap()->_bytesAllocSinceCM;
+    if (this->_last_bytesAllocSinceCM > 0) {
+      size_t min_garbage = this->_last_bytesAllocSinceCM;
+      region_set->choose_collection_and_free_sets_min_garbage(collection_set, free_set, min_garbage);
+    } else {
+      region_set->set_garbage_threshold(ShenandoahHeapRegion::RegionSizeBytes / 2);
+      region_set->choose_collection_and_free_sets(collection_set, free_set);
+    }
+    this->_max_live_data = MAX2(this->_max_live_data, collection_set->live_data());
+  }
+
+  void set_target_heap_occupancy(uintx target_heap_occupancy) {
+    this->_target_heap_occupancy_factor = get_percent(target_heap_occupancy);
+    this->_target_heap_occupancy = target_heap_occupancy;
+  }
+
+  void set_allocation_threshold(uintx allocationThreshold) {
+    this->_allocation_threshold_factor = get_percent(allocationThreshold);
+    this->_allocation_threshold = allocationThreshold;
+  }
+
+  uintx get_allocation_threshold() {
+    return this->_allocation_threshold;
+  }
+
+  uintx get_target_heap_occupancy() {
+    return this->_target_heap_occupancy;
+  }
+};
+
 
 static DynamicHeuristics *configureDynamicHeuristics() {
   DynamicHeuristics *heuristics = new DynamicHeuristics();
@@ -427,6 +529,19 @@
   return heuristics;
 }
 
+
+static NewAdaptiveHeuristics* configureNewAdaptiveHeuristics() {
+  NewAdaptiveHeuristics* heuristics = new NewAdaptiveHeuristics();
+
+  heuristics->set_target_heap_occupancy(ShenandoahTargetHeapOccupancy);
+  if (ShenandoahLogConfig) {
+    tty->print_cr( "Shenandoah newadaptive heuristics target heap occupancy: "SIZE_FORMAT,
+                   heuristics->get_target_heap_occupancy() );
+  }
+  return heuristics;
+}
+
+
 ShenandoahCollectorPolicy::ShenandoahCollectorPolicy() {
 
   ShenandoahHeapRegion::setup_heap_region_size(initial_heap_byte_size(), initial_heap_byte_size());
@@ -492,6 +607,11 @@
         tty->print_cr("Shenandoah heuristics: adaptive");
       }
       _heuristics = new AdaptiveHeuristics();
+    } else if (strcmp(ShenandoahGCHeuristics, "newadaptive") == 0) {
+      if (ShenandoahLogConfig) {
+        tty->print_cr("Shenandoah heuristics: newadaptive");
+      }
+      _heuristics = configureNewAdaptiveHeuristics();
     } else {
       fatal("Unknown -XX:ShenandoahGCHeuristics option");
     }
@@ -542,6 +662,15 @@
 void ShenandoahCollectorPolicy::record_bytes_allocated(size_t bytes) {
   _heuristics->record_bytes_allocated(bytes);
 }
+
+void ShenandoahCollectorPolicy::record_bytes_start_CM(size_t bytes) {
+  _heuristics->record_bytes_start_CM(bytes);
+}
+
+void ShenandoahCollectorPolicy::record_bytes_end_CM(size_t bytes) {
+  _heuristics->record_bytes_end_CM(bytes);
+}
+
 void ShenandoahCollectorPolicy::record_bytes_reclaimed(size_t bytes) {
   _heuristics->record_bytes_reclaimed(bytes);
 }
--- a/src/share/vm/gc_implementation/shenandoah/shenandoahCollectorPolicy.hpp	Tue Aug 11 13:01:06 2015 +0200
+++ b/src/share/vm/gc_implementation/shenandoah/shenandoahCollectorPolicy.hpp	Tue Aug 11 17:02:16 2015 -0400
@@ -93,6 +93,8 @@
 
   void record_bytes_allocated(size_t bytes);
   void record_bytes_reclaimed(size_t bytes);
+  void record_bytes_start_CM(size_t bytes);
+  void record_bytes_end_CM(size_t bytes);
   bool should_start_concurrent_mark(size_t used, size_t capacity);
   void choose_collection_and_free_sets(ShenandoahHeapRegionSet* region_set, 
                                        ShenandoahHeapRegionSet* collection_set,
--- a/src/share/vm/gc_implementation/shenandoah/shenandoahHeap.cpp	Tue Aug 11 13:01:06 2015 +0200
+++ b/src/share/vm/gc_implementation/shenandoah/shenandoahHeap.cpp	Tue Aug 11 17:02:16 2015 -0400
@@ -185,7 +185,7 @@
   _free_regions(NULL),
   _collection_set(NULL),
   _bytesAllocSinceCM(0),
-  _bytes_allocated_since_last_cm(0),
+  _bytes_allocated_during_cm(0),
   _max_allocated_gc(0),
   _allocated_last_gc(0),
   _used_start_gc(0),
--- a/src/share/vm/gc_implementation/shenandoah/shenandoahHeap.hpp	Tue Aug 11 13:01:06 2015 +0200
+++ b/src/share/vm/gc_implementation/shenandoah/shenandoahHeap.hpp	Tue Aug 11 17:02:16 2015 -0400
@@ -114,7 +114,8 @@
 
 public:
   size_t _bytesAllocSinceCM;
-  size_t _bytes_allocated_since_last_cm;
+  size_t _bytes_allocated_during_cm;
+  size_t _bytes_allocated_during_cm_start;
   size_t _max_allocated_gc;
   size_t _allocated_last_gc;
   size_t _used_start_gc;
--- a/src/share/vm/runtime/globals.hpp	Tue Aug 11 13:01:06 2015 +0200
+++ b/src/share/vm/runtime/globals.hpp	Tue Aug 11 17:02:16 2015 -0400
@@ -1647,6 +1647,11 @@
           "phase. Applies to Shenandoah GC dynamic Heuristic mode only "    \
           "(ignored otherwise)")                                            \
                                                                             \
+  product(uintx, ShenandoahTargetHeapOccupancy, 80,                         \
+          "Sets the target maximum percentage occupance of the heap we"     \
+          "would like to maintain."                                         \
+          "Shenandoah GC newadaptive Heuristic mode only.")                 \
+                                                                            \
   product(bool, ShenandoahPrintCollectionSet, false,                        \
           "Print the collection set before each GC phase")                  \
                                                                             \