< prev index next >
src/share/vm/gc/shenandoah/shenandoahCollectorPolicy.cpp
Print this page
*** 26,56 ****
#include "gc/shenandoah/shenandoahFreeSet.hpp"
#include "gc/shenandoah/shenandoahCollectorPolicy.hpp"
#include "gc/shenandoah/shenandoahHeap.inline.hpp"
#include "gc/shenandoah/shenandoahPhaseTimes.hpp"
- int compareHeapRegionsByGarbage(ShenandoahHeapRegion* a, ShenandoahHeapRegion* b) {
- if (a == NULL) {
- if (b == NULL) {
- return 0;
- } else {
- return 1;
- }
- } else if (b == NULL) {
- return -1;
- }
-
- size_t garbage_a = a->garbage();
- size_t garbage_b = b->garbage();
-
- if (garbage_a > garbage_b)
- return -1;
- else if (garbage_a < garbage_b)
- return 1;
- else return 0;
- }
-
class ShenandoahHeuristics : public CHeapObj<mtGC> {
NumberSeq _allocation_rate_bytes;
NumberSeq _reclamation_rate_bytes;
--- 26,35 ----
*** 59,71 ****
protected:
size_t _bytes_allocated_start_CM;
size_t _bytes_allocated_during_CM;
- private:
- size_t _garbage_threshold;
-
public:
ShenandoahHeuristics();
void record_bytes_allocated(size_t bytes);
--- 38,47 ----
*** 73,84 ****
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 void choose_collection_set(ShenandoahCollectionSet* collection_set);
! virtual void choose_collection_set_min_garbage(ShenandoahCollectionSet* collection_set, size_t min_garbage);
virtual void choose_free_set(ShenandoahFreeSet* free_set);
virtual bool process_references() {
if (ShenandoahRefProcFrequency == 0) return false;
size_t cycle = ShenandoahHeap::heap()->shenandoahPolicy()->cycle_counter();
--- 49,66 ----
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 void start_choose_collection_set() {
! }
! virtual void end_choose_collection_set() {
! }
! virtual bool region_in_collection_set(ShenandoahHeapRegion* r, size_t immediate_garbage) = 0;
!
! void choose_collection_set(ShenandoahCollectionSet* collection_set);
!
virtual void choose_free_set(ShenandoahFreeSet* free_set);
virtual bool process_references() {
if (ShenandoahRefProcFrequency == 0) return false;
size_t cycle = ShenandoahHeap::heap()->shenandoahPolicy()->cycle_counter();
*** 91,168 ****
size_t cycle = ShenandoahHeap::heap()->shenandoahPolicy()->cycle_counter();
// Process references every Nth GC cycle.
return cycle % ShenandoahUnloadClassesFrequency == 0;
}
! protected:
!
! void set_garbage_threshold(size_t threshold) {
! _garbage_threshold = threshold;
! }
- size_t garbage_threshold() {
- return _garbage_threshold;
- }
};
ShenandoahHeuristics::ShenandoahHeuristics() :
_bytes_allocated_since_CM(0),
_bytes_reclaimed_this_cycle(0),
_bytes_allocated_start_CM(0),
! _bytes_allocated_during_CM(0),
! _garbage_threshold(ShenandoahHeapRegion::RegionSizeBytes / 2)
{
}
void ShenandoahHeuristics::choose_collection_set(ShenandoahCollectionSet* collection_set) {
ShenandoahHeapRegionSet* sorted_regions = ShenandoahHeap::heap()->sorted_regions();
sorted_regions->sort(compareHeapRegionsByGarbage);
size_t i = 0;
size_t end = sorted_regions->active_regions();
ShenandoahHeap* heap = ShenandoahHeap::heap();
! while (i < end) {
! ShenandoahHeapRegion* region = sorted_regions->get(i++);
! if (region->garbage() > _garbage_threshold && ! region->is_humongous() && ! region->is_pinned()) {
! log_develop_trace(gc)("Choose region " SIZE_FORMAT " with garbage = " SIZE_FORMAT
! " and live = " SIZE_FORMAT " and _garbage_threshold = " SIZE_FORMAT "\n",
! region->region_number(), region->garbage(), region->get_live_data(), _garbage_threshold);
!
! assert(! region->is_humongous(), "no humongous regions in collection set");
! if (region->get_live_data() == 0) {
// We can recycle it right away and put it in the free set.
heap->decrease_used(region->used());
region->recycle();
! } else {
collection_set->add_region(region);
region->set_in_collection_set(true);
}
} else {
log_develop_trace(gc)("Rejected region " SIZE_FORMAT " with garbage = " SIZE_FORMAT
! " and live = " SIZE_FORMAT " and _garbage_threshold = " SIZE_FORMAT "\n",
! region->region_number(), region->garbage(), region->get_live_data(), _garbage_threshold);
}
}
! }
!
! void ShenandoahHeuristics::choose_collection_set_min_garbage(ShenandoahCollectionSet* collection_set, size_t min_garbage) {
! ShenandoahHeapRegionSet* sorted_regions = ShenandoahHeap::heap()->sorted_regions();
! sorted_regions->sort(compareHeapRegionsByGarbage);
! size_t i = 0;
! size_t end = sorted_regions->active_regions();
! size_t garbage = 0;
! while (i < end && garbage < min_garbage) {
! ShenandoahHeapRegion* region = sorted_regions->get(i++);
! if (region->garbage() > _garbage_threshold && ! region->is_humongous() && ! region->is_pinned()) {
! collection_set->add_region(region);
! garbage += region->garbage();
! region->set_in_collection_set(true);
! }
! }
}
void ShenandoahHeuristics::choose_free_set(ShenandoahFreeSet* free_set) {
ShenandoahHeapRegionSet* ordered_regions = ShenandoahHeap::heap()->regions();
--- 73,165 ----
size_t cycle = ShenandoahHeap::heap()->shenandoahPolicy()->cycle_counter();
// Process references every Nth GC cycle.
return cycle % ShenandoahUnloadClassesFrequency == 0;
}
! private:
! static int compareHeapRegionsByGarbage(ShenandoahHeapRegion* a, ShenandoahHeapRegion* b);
};
ShenandoahHeuristics::ShenandoahHeuristics() :
_bytes_allocated_since_CM(0),
_bytes_reclaimed_this_cycle(0),
_bytes_allocated_start_CM(0),
! _bytes_allocated_during_CM(0)
{
}
+ int ShenandoahHeuristics::compareHeapRegionsByGarbage(ShenandoahHeapRegion* a, ShenandoahHeapRegion* b) {
+ if (a == NULL) {
+ if (b == NULL) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else if (b == NULL) {
+ return -1;
+ }
+
+ size_t garbage_a = a->garbage();
+ size_t garbage_b = b->garbage();
+
+ if (garbage_a > garbage_b)
+ return -1;
+ else if (garbage_a < garbage_b)
+ return 1;
+ else return 0;
+ }
+
void ShenandoahHeuristics::choose_collection_set(ShenandoahCollectionSet* collection_set) {
ShenandoahHeapRegionSet* sorted_regions = ShenandoahHeap::heap()->sorted_regions();
sorted_regions->sort(compareHeapRegionsByGarbage);
+ start_choose_collection_set();
+
size_t i = 0;
size_t end = sorted_regions->active_regions();
ShenandoahHeap* heap = ShenandoahHeap::heap();
! size_t total_garbage = heap->garbage();
! size_t immediate_garbage = 0;
! size_t immediate_regions = 0;
! for (size_t i = 0; i < end; i++) {
! ShenandoahHeapRegion* region = sorted_regions->get(i);
! if (! region->is_humongous() && ! region->is_pinned()) {
! if ((! region->is_empty()) && region->get_live_data() == 0) {
// We can recycle it right away and put it in the free set.
+ immediate_regions++;
+ immediate_garbage += region->garbage();
heap->decrease_used(region->used());
region->recycle();
! log_develop_trace(gc)("Choose region for immediate" SIZE_FORMAT " with garbage = " SIZE_FORMAT
! " and live = " SIZE_FORMAT "\n",
! region->region_number(), region->garbage(), region->get_live_data());
! } else if (region_in_collection_set(region, immediate_garbage)) {
! log_develop_trace(gc)("Choose region " SIZE_FORMAT " with garbage = " SIZE_FORMAT
! " and live = " SIZE_FORMAT "\n",
! region->region_number(), region->garbage(), region->get_live_data());
collection_set->add_region(region);
region->set_in_collection_set(true);
}
} else {
+ assert(region->get_live_data() != 0 || region->is_empty() || region->is_pinned() || region->is_humongous(), "check rejected");
log_develop_trace(gc)("Rejected region " SIZE_FORMAT " with garbage = " SIZE_FORMAT
! " and live = " SIZE_FORMAT "\n",
! region->region_number(), region->garbage(), region->get_live_data());
}
}
! end_choose_collection_set();
! log_debug(gc)("Total Garbage: "SIZE_FORMAT, total_garbage);
! log_debug(gc)("Immediate Garbage: "SIZE_FORMAT, immediate_garbage);
! log_debug(gc)("Immediate Garbage regions: "SIZE_FORMAT, immediate_regions);
! log_debug(gc)("Garbage to be collected: "SIZE_FORMAT, collection_set->garbage());
! log_debug(gc)("Objects to be evacuated: "SIZE_FORMAT, collection_set->live_data());
! log_debug(gc)("Live / Garbage ratio: "SIZE_FORMAT"%%", collection_set->live_data() * 100 / MAX2(collection_set->garbage(), 1UL));
! log_debug(gc)("Collected-Garbage ratio / Total-garbage: "SIZE_FORMAT"%%", collection_set->garbage() * 100 / MAX2(total_garbage, 1UL));
}
void ShenandoahHeuristics::choose_free_set(ShenandoahFreeSet* free_set) {
ShenandoahHeapRegionSet* ordered_regions = ShenandoahHeap::heap()->regions();
*** 231,241 ****
}
class PassiveHeuristics : public ShenandoahHeuristics {
public:
PassiveHeuristics() : ShenandoahHeuristics() {
! set_garbage_threshold(8);
}
virtual bool should_start_concurrent_mark(size_t used, size_t capacity) const {
// Never do concurrent GCs.
return false;
--- 228,241 ----
}
class PassiveHeuristics : public ShenandoahHeuristics {
public:
PassiveHeuristics() : ShenandoahHeuristics() {
! }
!
! virtual bool region_in_collection_set(ShenandoahHeapRegion* r, size_t immediate_garbage) {
! return r->garbage() > 0;
}
virtual bool should_start_concurrent_mark(size_t used, size_t capacity) const {
// Never do concurrent GCs.
return false;
*** 253,263 ****
};
class AggressiveHeuristics : public ShenandoahHeuristics {
public:
AggressiveHeuristics() : ShenandoahHeuristics() {
! set_garbage_threshold(8);
}
virtual bool should_start_concurrent_mark(size_t used, size_t capacity) const {
return true;
}
--- 253,266 ----
};
class AggressiveHeuristics : public ShenandoahHeuristics {
public:
AggressiveHeuristics() : ShenandoahHeuristics() {
! }
!
! virtual bool region_in_collection_set(ShenandoahHeapRegion* r, size_t immediate_garbage) {
! return r->garbage() > 0;
}
virtual bool should_start_concurrent_mark(size_t used, size_t capacity) const {
return true;
}
*** 274,284 ****
};
class DynamicHeuristics : public ShenandoahHeuristics {
public:
DynamicHeuristics() : ShenandoahHeuristics() {
! log_info(gc, init)("Shenandoah dynamic heuristics thresholds: allocation "SIZE_FORMAT", free "SIZE_FORMAT", garbage "SIZE_FORMAT,
ShenandoahAllocationThreshold,
ShenandoahFreeThreshold,
ShenandoahGarbageThreshold);
}
--- 277,287 ----
};
class DynamicHeuristics : public ShenandoahHeuristics {
public:
DynamicHeuristics() : ShenandoahHeuristics() {
! log_info(gc, init)("Shenandoah heuristics thresholds: allocation "SIZE_FORMAT", free "SIZE_FORMAT", garbage "SIZE_FORMAT,
ShenandoahAllocationThreshold,
ShenandoahFreeThreshold,
ShenandoahGarbageThreshold);
}
*** 306,319 ****
}
return shouldStartConcurrentMark;
}
! virtual void choose_collection_set(ShenandoahCollectionSet* collection_set) {
! set_garbage_threshold(ShenandoahHeapRegion::RegionSizeBytes * ShenandoahGarbageThreshold / 100);
! ShenandoahHeuristics::choose_collection_set(collection_set);
}
};
class AdaptiveHeuristics : public ShenandoahHeuristics {
private:
--- 309,323 ----
}
return shouldStartConcurrentMark;
}
! virtual bool region_in_collection_set(ShenandoahHeapRegion* r, size_t immediate_garbage) {
! size_t threshold = ShenandoahHeapRegion::RegionSizeBytes * ShenandoahGarbageThreshold / 100;
! return r->garbage() > threshold;
}
+
};
class AdaptiveHeuristics : public ShenandoahHeuristics {
private:
*** 324,333 ****
--- 328,338 ----
uintx _used_threshold;
uintx _garbage_threshold;
uintx _allocation_threshold;
+ size_t _garbage;
public:
AdaptiveHeuristics() : ShenandoahHeuristics() {
_max_live_data = 0;
_used_threshold = 0;
*** 339,348 ****
--- 344,369 ----
_allocation_threshold_factor = 0.;
}
virtual ~AdaptiveHeuristics() {}
+ virtual void start_choose_collection_set() {
+ _garbage = 0;
+ }
+
+ virtual bool region_in_collection_set(ShenandoahHeapRegion* r, size_t immediate_garbage) {
+ size_t bytes_alloc = ShenandoahHeap::heap()->bytes_allocated_since_cm();
+ size_t min_garbage = bytes_alloc/* * 1.1*/;
+ size_t threshold = ShenandoahHeapRegion::RegionSizeBytes * ShenandoahGarbageThreshold / 100;
+ if (_garbage < min_garbage && r->garbage() > threshold) {
+ _garbage += r->garbage();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
virtual bool should_start_concurrent_mark(size_t used, size_t capacity) const {
ShenandoahHeap* _heap = ShenandoahHeap::heap();
bool shouldStartConcurrentMark = false;
OrderAccess::release();
*** 366,385 ****
}
return shouldStartConcurrentMark;
}
! virtual void choose_collection_set(ShenandoahCollectionSet* collection_set) {
! size_t bytes_alloc = ShenandoahHeap::heap()->bytes_allocated_since_cm();
! size_t min_garbage = bytes_alloc/* * 1.1*/;
! set_garbage_threshold(ShenandoahHeapRegion::RegionSizeBytes * ShenandoahGarbageThreshold / 100);
! ShenandoahHeuristics::choose_collection_set_min_garbage(collection_set, min_garbage);
! log_develop_trace(gc)("Garbage to be collected: "SIZE_FORMAT, collection_set->garbage());
! log_develop_trace(gc)("Objects to be evacuated: "SIZE_FORMAT, collection_set->live_data());
! _max_live_data = MAX2(_max_live_data, collection_set->live_data());
}
};
ShenandoahCollectorPolicy::ShenandoahCollectorPolicy() : _cycle_counter(0) {
--- 387,453 ----
}
return shouldStartConcurrentMark;
}
! };
!
! class GlobalHeuristics : public DynamicHeuristics {
! private:
! size_t _garbage;
! size_t _min_garbage;
! public:
! GlobalHeuristics() : DynamicHeuristics() {
! if (FLAG_IS_DEFAULT(ShenandoahGarbageThreshold)) {
! FLAG_SET_DEFAULT(ShenandoahGarbageThreshold, 90);
! }
! }
! virtual ~GlobalHeuristics() {}
! virtual void start_choose_collection_set() {
! _garbage = 0;
! size_t heap_garbage = ShenandoahHeap::heap()->garbage();
! _min_garbage = heap_garbage * ShenandoahGarbageThreshold / 100;
! }
!
! virtual bool region_in_collection_set(ShenandoahHeapRegion* r, size_t immediate_garbage) {
! if (_garbage + immediate_garbage < _min_garbage) {
! _garbage += r->garbage();
! return true;
! } else {
! return false;
! }
! }
! };
!
! class RatioHeuristics : public DynamicHeuristics {
! private:
! size_t _garbage;
! size_t _live;
! public:
! RatioHeuristics() : DynamicHeuristics() {
! if (FLAG_IS_DEFAULT(ShenandoahGarbageThreshold)) {
! FLAG_SET_DEFAULT(ShenandoahGarbageThreshold, 95);
! }
! }
! virtual ~RatioHeuristics() {}
!
! virtual void start_choose_collection_set() {
! _garbage = 0;
! _live = 0;
! }
!
! virtual bool region_in_collection_set(ShenandoahHeapRegion* r, size_t immediate_garbage) {
! size_t min_ratio = 100 - ShenandoahGarbageThreshold;
! if (_live * 100 / MAX2(_garbage + immediate_garbage, 1UL) < min_ratio) {
! _garbage += r->garbage();
! _live += r->get_live_data();
! return true;
! } else {
! return false;
! }
}
};
ShenandoahCollectorPolicy::ShenandoahCollectorPolicy() : _cycle_counter(0) {
*** 469,478 ****
--- 537,552 ----
log_info(gc, init)("Shenandoah heuristics: aggressive");
_heuristics = new AggressiveHeuristics();
} else if (strcmp(ShenandoahGCHeuristics, "dynamic") == 0) {
log_info(gc, init)("Shenandoah heuristics: dynamic");
_heuristics = new DynamicHeuristics();
+ } else if (strcmp(ShenandoahGCHeuristics, "global") == 0) {
+ log_info(gc, init)("Shenandoah heuristics: global");
+ _heuristics = new GlobalHeuristics();
+ } else if (strcmp(ShenandoahGCHeuristics, "ratio") == 0) {
+ log_info(gc, init)("Shenandoah heuristics: ratio");
+ _heuristics = new RatioHeuristics();
} else if (strcmp(ShenandoahGCHeuristics, "adaptive") == 0) {
log_info(gc, init)("Shenandoah heuristics: adaptive");
_heuristics = new AdaptiveHeuristics();
} else if (strcmp(ShenandoahGCHeuristics, "passive") == 0) {
log_info(gc, init)("Shenandoah heuristics: passive");
< prev index next >