< 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 >