< prev index next >

src/share/vm/gc/shenandoah/shenandoahCollectorPolicy.cpp

Print this page
rev 13320 : Use peak occupancy to optimize/pessimize free_threshold in adaptive heuristics.

@@ -144,10 +144,13 @@
 
   virtual void record_full_gc() {
     _bytes_in_cset = 0;
   }
 
+  virtual void record_peak_occupancy() {
+  }
+
   virtual void start_choose_collection_set() {
   }
   virtual void end_choose_collection_set() {
   }
   virtual bool region_in_collection_set(ShenandoahHeapRegion* r, size_t immediate_garbage) = 0;

@@ -467,15 +470,16 @@
 
 class AdaptiveHeuristics : public ShenandoahHeuristics {
 private:
   uintx _free_threshold;
   TruncatedSeq* _cset_history;
-
+  size_t _peak_occupancy;
 public:
   AdaptiveHeuristics() :
     ShenandoahHeuristics(),
     _free_threshold(ShenandoahInitFreeThreshold),
+    _peak_occupancy(0),
     _cset_history(new TruncatedSeq((uint)ShenandoahHappyCyclesThreshold)) {
 
     _cset_history->add((double) ShenandoahCSetThreshold);
     _cset_history->add((double) ShenandoahCSetThreshold);
   }

@@ -487,13 +491,25 @@
   virtual bool region_in_collection_set(ShenandoahHeapRegion* r, size_t immediate_garbage) {
     size_t threshold = ShenandoahHeapRegion::region_size_bytes() * ShenandoahGarbageThreshold / 100;
     return r->garbage() > threshold;
   }
 
+  void handle_gc_success(uint successful_cycles) {
+    ShenandoahHeap* heap = ShenandoahHeap::heap();
+    size_t capacity = heap->capacity();
+    size_t available = heap->capacity() - _peak_occupancy;
+    if (available * 100 / capacity <= ShenandoahMinFreeThreshold) {
+      pessimize_free_threshold();
+    } else {
+      optimize_free_threshold(successful_cycles);
+    }
+    _peak_occupancy = 0;
+  }
+
   void optimize_free_threshold(uint successful_cycles) {
     if (successful_cycles > ShenandoahHappyCyclesThreshold &&
-        _free_threshold > ShenandoahMinFreeThreshold) {
+        _free_threshold > 0) {
       _free_threshold--;
       log_info(gc,ergo)("reducing free threshold to: "UINTX_FORMAT, _free_threshold);
       _successful_cm_cycles_in_a_row = 0;
     }
   }

@@ -511,29 +527,32 @@
   }
 
   virtual void record_cm_success() {
     ShenandoahHeuristics::record_cm_success();
     if (! update_refs_early()) {
-      optimize_free_threshold(_successful_cm_cycles_in_a_row);
+      handle_gc_success(_successful_cm_cycles_in_a_row);
     }
   }
 
   virtual void record_uprefs_cancelled() {
     ShenandoahHeuristics::record_uprefs_cancelled();
     pessimize_free_threshold();
   }
 
   virtual void record_uprefs_success() {
     ShenandoahHeuristics::record_uprefs_success();
-    optimize_free_threshold(_successful_uprefs_cycles_in_a_row);
+    handle_gc_success(_successful_uprefs_cycles_in_a_row);
   }
 
   virtual void record_full_gc() {
     ShenandoahHeuristics::record_full_gc();
     pessimize_free_threshold();
   }
 
+  virtual void record_peak_occupancy() {
+    _peak_occupancy = MAX2(_peak_occupancy, ShenandoahHeap::heap()->used());
+  }
 
   virtual bool should_start_concurrent_mark(size_t used, size_t capacity) const {
     bool shouldStartConcurrentMark = false;
 
     ShenandoahHeap* heap = ShenandoahHeap::heap();

@@ -1030,10 +1049,14 @@
 
 void ShenandoahCollectorPolicy::record_full_gc() {
   _heuristics->record_full_gc();
 }
 
+void ShenandoahCollectorPolicy::record_peak_occupancy() {
+  _heuristics->record_peak_occupancy();
+}
+
 void ShenandoahCollectorPolicy::choose_collection_set(ShenandoahCollectionSet* collection_set, int* connections) {
   _heuristics->choose_collection_set(collection_set, connections);
 }
 
 void ShenandoahCollectorPolicy::choose_free_set(ShenandoahFreeSet* free_set) {
< prev index next >