< prev index next >

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

Print this page
rev 50076 : Fold Partial GC into Traversal GC

*** 26,36 **** #include "gc/shenandoah/shenandoahCollectionSet.hpp" #include "gc/shenandoah/shenandoahConnectionMatrix.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" ! #include "gc/shenandoah/shenandoahPartialGC.hpp" #include "runtime/os.hpp" #include "utilities/quickSort.hpp" #define SHENANDOAH_ERGO_DISABLE_FLAG(name) \ do { \ --- 26,36 ---- #include "gc/shenandoah/shenandoahCollectionSet.hpp" #include "gc/shenandoah/shenandoahConnectionMatrix.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" ! #include "gc/shenandoah/shenandoahTraversalGC.hpp" #include "runtime/os.hpp" #include "utilities/quickSort.hpp" #define SHENANDOAH_ERGO_DISABLE_FLAG(name) \ do { \
*** 177,196 **** virtual bool update_refs() const { return _update_refs_early; } ! virtual bool should_start_partial_gc() { ! return false; ! } ! ! virtual bool can_do_partial_gc() { ! return false; ! } ! ! virtual bool should_start_traversal_gc() { ! return false; } virtual bool can_do_traversal_gc() { return false; } --- 177,188 ---- virtual bool update_refs() const { return _update_refs_early; } ! virtual ShenandoahHeap::GCCycleMode should_start_traversal_gc() { ! return ShenandoahHeap::NONE; } virtual bool can_do_traversal_gc() { return false; }
*** 406,421 **** // Passive runs with max speed, reacts on allocation failure. FLAG_SET_DEFAULT(ShenandoahPacing, false); // Disable known barriers by default. SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahSATBBarrier); - SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahConditionalSATBBarrier); SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahKeepAliveBarrier); SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahWriteBarrier); SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahReadBarrier); SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahStoreValEnqueueBarrier); - SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahStoreValWriteBarrier); SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahStoreValReadBarrier); SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahCASBarrier); SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahAcmpBarrier); SHENANDOAH_ERGO_DISABLE_FLAG(ShenandoahCloneBarrier); SHENANDOAH_ERGO_DISABLE_FLAG(UseShenandoahMatrix); --- 398,411 ----
*** 883,907 **** virtual bool is_experimental() { return false; } }; ! class ShenandoahPartialHeuristics : public ShenandoahAdaptiveHeuristics { protected: - size_t* _from_idxs; public: ! ShenandoahPartialHeuristics() : ShenandoahAdaptiveHeuristics() { ! FLAG_SET_DEFAULT(UseShenandoahMatrix, true); ! ! // Set up special barriers for concurrent partial GC. ! FLAG_SET_DEFAULT(ShenandoahConditionalSATBBarrier, true); FLAG_SET_DEFAULT(ShenandoahSATBBarrier, false); - FLAG_SET_DEFAULT(ShenandoahStoreValWriteBarrier, true); FLAG_SET_DEFAULT(ShenandoahStoreValReadBarrier, false); SHENANDOAH_ERGO_OVERRIDE_DEFAULT(ShenandoahRefProcFrequency, 1); // TODO: Disable this optimization for now, as it also requires the matrix barriers. #ifdef COMPILER2 FLAG_SET_DEFAULT(ArrayCopyLoadStoreMaxElem, 0); #endif } --- 873,1010 ---- virtual bool is_experimental() { return false; } }; ! class ShenandoahTraversalHeuristics : public ShenandoahHeuristics { protected: public: ! ShenandoahTraversalHeuristics() : ShenandoahHeuristics() { ! FLAG_SET_DEFAULT(UseShenandoahMatrix, false); FLAG_SET_DEFAULT(ShenandoahSATBBarrier, false); FLAG_SET_DEFAULT(ShenandoahStoreValReadBarrier, false); + FLAG_SET_DEFAULT(ShenandoahStoreValEnqueueBarrier, true); + FLAG_SET_DEFAULT(ShenandoahKeepAliveBarrier, false); + FLAG_SET_DEFAULT(ShenandoahBarriersForConst, true); + FLAG_SET_DEFAULT(ShenandoahWriteBarrierRB, false); + FLAG_SET_DEFAULT(ShenandoahAllocImplicitLive, false); + FLAG_SET_DEFAULT(ShenandoahAllowMixedAllocs, false); + FLAG_SET_DEFAULT(ShenandoahRecycleClearsBitmap, true); SHENANDOAH_ERGO_OVERRIDE_DEFAULT(ShenandoahRefProcFrequency, 1); + SHENANDOAH_ERGO_OVERRIDE_DEFAULT(ShenandoahUnloadClassesFrequency, 1); + + } + + virtual bool should_start_normal_gc() const { + return false; + } + + virtual bool is_experimental() { + return true; + } + + virtual bool is_diagnostic() { + return false; + } + + virtual bool can_do_traversal_gc() { + return true; + } + + virtual const char* name() { + return "traversal"; + } + + virtual void choose_collection_set(ShenandoahCollectionSet* collection_set) { + ShenandoahHeap* heap = ShenandoahHeap::heap(); + + // No root regions in this mode. + ShenandoahTraversalGC* traversal_gc = heap->traversal_gc(); + ShenandoahHeapRegionSet* root_regions = traversal_gc->root_regions(); + root_regions->clear(); + + ShenandoahHeapRegionSet* traversal_set = traversal_gc->traversal_set(); + traversal_set->clear(); + for (size_t i = 0; i < heap->num_regions(); i++) { + ShenandoahHeapRegion* r = heap->get_region(i); + assert(!collection_set->is_in(r), "must not yet be in cset"); + if (r->is_regular() && r->used() > 0) { + size_t garbage_percent = r->garbage() * 100 / ShenandoahHeapRegion::region_size_bytes(); + if (garbage_percent > ShenandoahGarbageThreshold) { + collection_set->add_region(r); + } + } + r->clear_live_data(); + traversal_set->add_region(r); + } + collection_set->update_region_status(); + } + + virtual ShenandoahHeap::GCCycleMode should_start_traversal_gc() { + + ShenandoahHeap* heap = ShenandoahHeap::heap(); + + if (heap->has_forwarded_objects()) return ShenandoahHeap::NONE; + + double last_time_ms = (os::elapsedTime() - _last_cycle_end) * 1000; + bool periodic_gc = (last_time_ms > ShenandoahGuaranteedGCInterval); + if (periodic_gc) { + log_info(gc,ergo)("Periodic GC triggered. Time since last GC: %.0f ms, Guaranteed Interval: " UINTX_FORMAT " ms", + last_time_ms, ShenandoahGuaranteedGCInterval); + return ShenandoahHeap::MAJOR; + } + + size_t capacity = heap->capacity(); + size_t used = heap->used(); + return 100 - (used * 100 / capacity) < ShenandoahFreeThreshold ? ShenandoahHeap::MAJOR : ShenandoahHeap::NONE; + } + + protected: + virtual void choose_collection_set_from_regiondata(ShenandoahCollectionSet* set, + RegionData* data, size_t data_size, + size_t free) { + ShouldNotReachHere(); + } + }; + + class ShenandoahPartialHeuristics : public ShenandoahTraversalHeuristics { + protected: + size_t* _from_idxs; + + bool is_minor_gc() const { return ShenandoahHeap::heap()->is_minor_gc(); } + + // Utility method to remove any cset regions from root set and + // add all cset regions to the traversal set. + void filter_regions() { + ShenandoahHeap* heap = ShenandoahHeap::heap(); + ShenandoahTraversalGC* traversal_gc = heap->traversal_gc(); + size_t num_regions = heap->num_regions(); + ShenandoahCollectionSet* collection_set = heap->collection_set(); + ShenandoahHeapRegionSet* root_regions = traversal_gc->root_regions(); + ShenandoahHeapRegionSet* traversal_set = traversal_gc->traversal_set(); + traversal_set->clear(); + + for (size_t i = 0; i < num_regions; i++) { + ShenandoahHeapRegion* region = heap->get_region(i); + if (collection_set->is_in(i)) { + if (root_regions->is_in(i)) { + root_regions->remove_region(region); + } + traversal_set->add_region_check_for_duplicates(region); + assert(traversal_set->is_in(i), "must be in traversal set now"); + } + } + } + + public: + ShenandoahPartialHeuristics() : + ShenandoahTraversalHeuristics() { + + FLAG_SET_DEFAULT(UseShenandoahMatrix, true); + // TODO: Disable this optimization for now, as it also requires the matrix barriers. #ifdef COMPILER2 FLAG_SET_DEFAULT(ArrayCopyLoadStoreMaxElem, 0); #endif }
*** 913,931 **** virtual ~ShenandoahPartialHeuristics() { FREE_C_HEAP_ARRAY(size_t, _from_idxs); } bool should_start_update_refs() { ! return true; } bool update_refs() const { ! return true; } ! bool can_do_partial_gc() { ! return true; } bool should_start_normal_gc() const { return false; } --- 1016,1038 ---- virtual ~ShenandoahPartialHeuristics() { FREE_C_HEAP_ARRAY(size_t, _from_idxs); } bool should_start_update_refs() { ! return false; } bool update_refs() const { ! return false; } ! virtual bool should_unload_classes() { ! return ShenandoahUnloadClassesFrequency != 0; ! } ! ! virtual bool should_process_references() { ! return ShenandoahRefProcFrequency != 0; } bool should_start_normal_gc() const { return false; }
*** 936,971 **** virtual bool is_experimental() { return true; } - virtual bool should_start_partial_gc() = 0; - virtual void choose_collection_set(ShenandoahCollectionSet* collection_set) = 0; - }; class ShenandoahPartialConnectedHeuristics : public ShenandoahPartialHeuristics { public: virtual const char* name() { return "connectedness"; } ! bool should_start_partial_gc() { ShenandoahHeap* heap = ShenandoahHeap::heap(); if (heap->has_forwarded_objects()) { // Cannot start partial if heap is not completely updated. ! return false; } size_t capacity = heap->capacity(); size_t used = heap->used(); size_t prev_used = heap->used_at_last_gc(); if (used < prev_used) { // Major collection must have happened, "used" data is unreliable, wait for update. ! return false; } size_t threshold = heap->capacity() * ShenandoahConnectednessPercentage / 100; size_t allocated = used - prev_used; bool result = allocated > threshold; --- 1043,1080 ---- virtual bool is_experimental() { return true; } }; class ShenandoahPartialConnectedHeuristics : public ShenandoahPartialHeuristics { public: virtual const char* name() { return "connectedness"; } ! ShenandoahHeap::GCCycleMode should_start_traversal_gc() { ! ShenandoahHeap::GCCycleMode cycle_mode = ShenandoahPartialHeuristics::should_start_traversal_gc(); ! if (cycle_mode != ShenandoahHeap::NONE) { ! return cycle_mode; ! } ! ShenandoahHeap* heap = ShenandoahHeap::heap(); if (heap->has_forwarded_objects()) { // Cannot start partial if heap is not completely updated. ! return ShenandoahHeap::NONE; } size_t capacity = heap->capacity(); size_t used = heap->used(); size_t prev_used = heap->used_at_last_gc(); if (used < prev_used) { // Major collection must have happened, "used" data is unreliable, wait for update. ! return ShenandoahHeap::NONE; } size_t threshold = heap->capacity() * ShenandoahConnectednessPercentage / 100; size_t allocated = used - prev_used; bool result = allocated > threshold;
*** 978,1001 **** if (result) { log_info(gc,ergo)("%s", msg.buffer()); } else { log_trace(gc,ergo)("%s", msg.buffer()); } ! return result; } void choose_collection_set(ShenandoahCollectionSet* collection_set) { ShenandoahHeap* heap = ShenandoahHeap::heap(); ShenandoahConnectionMatrix* matrix = heap->connection_matrix(); size_t num_regions = heap->num_regions(); RegionConnections* connects = get_region_connects_cache(num_regions); size_t connect_cnt = 0; for (uint to_idx = 0; to_idx < num_regions; to_idx++) { ShenandoahHeapRegion* region = heap->get_region(to_idx); - region->set_root(false); if (!region->is_regular()) continue; uint count = matrix->count_connected_to(to_idx, num_regions); if (count < ShenandoahPartialInboundThreshold) { connects[connect_cnt]._region = region; --- 1087,1116 ---- if (result) { log_info(gc,ergo)("%s", msg.buffer()); } else { log_trace(gc,ergo)("%s", msg.buffer()); } ! return result ? ShenandoahHeap::MINOR : ShenandoahHeap::NONE; } void choose_collection_set(ShenandoahCollectionSet* collection_set) { + if (!is_minor_gc()) { + return ShenandoahPartialHeuristics::choose_collection_set(collection_set); + } + ShenandoahHeap* heap = ShenandoahHeap::heap(); + ShenandoahTraversalGC* traversal_gc = heap->traversal_gc(); ShenandoahConnectionMatrix* matrix = heap->connection_matrix(); + ShenandoahHeapRegionSet* root_regions = traversal_gc->root_regions(); + root_regions->clear(); size_t num_regions = heap->num_regions(); RegionConnections* connects = get_region_connects_cache(num_regions); size_t connect_cnt = 0; for (uint to_idx = 0; to_idx < num_regions; to_idx++) { ShenandoahHeapRegion* region = heap->get_region(to_idx); if (!region->is_regular()) continue; uint count = matrix->count_connected_to(to_idx, num_regions); if (count < ShenandoahPartialInboundThreshold) { connects[connect_cnt]._region = region;
*** 1027,1043 **** _from_idxs, from_idx_count, ShenandoahPartialInboundThreshold)) { maybe_add_heap_region(region, collection_set); for (size_t i = 0; i < from_idx_count; i++) { ShenandoahHeapRegion* r = heap->get_region(_from_idxs[i]); ! if (!r->is_root()) { ! r->set_root(true); ! } } } } ! collection_set->update_region_status(); } }; class ShenandoahGenerationalPartialHeuristics : public ShenandoahPartialHeuristics { --- 1142,1156 ---- _from_idxs, from_idx_count, ShenandoahPartialInboundThreshold)) { maybe_add_heap_region(region, collection_set); for (size_t i = 0; i < from_idx_count; i++) { ShenandoahHeapRegion* r = heap->get_region(_from_idxs[i]); ! root_regions->add_region_check_for_duplicates(r); } } } ! filter_regions(); collection_set->update_region_status(); } }; class ShenandoahGenerationalPartialHeuristics : public ShenandoahPartialHeuristics {
*** 1050,1060 **** --- 1163,1178 ---- virtual const char* name() { return "generational"; } virtual void choose_collection_set(ShenandoahCollectionSet* collection_set) { + if (!is_minor_gc()) { + return ShenandoahPartialHeuristics::choose_collection_set(collection_set); + } + ShenandoahHeap* heap = ShenandoahHeap::heap(); + ShenandoahTraversalGC* traversal_gc = heap->traversal_gc(); ShenandoahConnectionMatrix* matrix = heap->connection_matrix(); uint64_t alloc_seq_at_last_gc_end = heap->alloc_seq_at_last_gc_end(); uint64_t alloc_seq_at_last_gc_start = heap->alloc_seq_at_last_gc_start(); size_t num_regions = heap->num_regions();
*** 1074,1087 **** size_t used = heap->used(); size_t prev_used = heap->used_at_last_gc(); guarantee(used >= prev_used, "Invariant"); size_t target = MIN2(ShenandoahHeapRegion::required_regions(used - prev_used), num_regions); ! for (uint to_idx = 0; to_idx < num_regions; to_idx++) { ! ShenandoahHeapRegion* region = heap->get_region(to_idx); ! region->set_root(false); ! } uint count = 0; for (uint i = 0; (i < num_regions) && (count < target); i++) { ShenandoahHeapRegion* contender = candidates[i]._region; --- 1192,1203 ---- size_t used = heap->used(); size_t prev_used = heap->used_at_last_gc(); guarantee(used >= prev_used, "Invariant"); size_t target = MIN2(ShenandoahHeapRegion::required_regions(used - prev_used), num_regions); ! ShenandoahHeapRegionSet* root_regions = traversal_gc->root_regions(); ! root_regions->clear(); uint count = 0; for (uint i = 0; (i < num_regions) && (count < target); i++) { ShenandoahHeapRegion* contender = candidates[i]._region;
*** 1097,1133 **** count++; } for (uint f = 0; f < from_idx_count; f++) { ShenandoahHeapRegion* r = heap->get_region(_from_idxs[f]); ! if (!r->is_root()) { ! r->set_root(true); ! } } } } collection_set->update_region_status(); log_info(gc,ergo)("Regions: Max: " SIZE_FORMAT ", Target: " SIZE_FORMAT " (" SIZE_FORMAT "%%), In CSet: " SIZE_FORMAT, num_regions, target, ShenandoahGenerationalYoungGenPercentage, collection_set->count()); } ! bool should_start_partial_gc() { ShenandoahHeap* heap = ShenandoahHeap::heap(); if (heap->has_forwarded_objects()) { // Cannot start partial if heap is not completely updated. ! return false; } size_t capacity = heap->capacity(); size_t used = heap->used(); size_t prev_used = heap->used_at_last_gc(); if (used < prev_used) { // Major collection must have happened, "used" data is unreliable, wait for update. ! return false; } size_t threshold = heap->capacity() * ShenandoahGenerationalYoungGenPercentage / 100; size_t allocated = used - prev_used; --- 1213,1253 ---- count++; } for (uint f = 0; f < from_idx_count; f++) { ShenandoahHeapRegion* r = heap->get_region(_from_idxs[f]); ! root_regions->add_region_check_for_duplicates(r); } } } + filter_regions(); collection_set->update_region_status(); log_info(gc,ergo)("Regions: Max: " SIZE_FORMAT ", Target: " SIZE_FORMAT " (" SIZE_FORMAT "%%), In CSet: " SIZE_FORMAT, num_regions, target, ShenandoahGenerationalYoungGenPercentage, collection_set->count()); } ! ShenandoahHeap::GCCycleMode should_start_traversal_gc() { ! ShenandoahHeap::GCCycleMode cycle_mode = ShenandoahPartialHeuristics::should_start_traversal_gc(); ! if (cycle_mode != ShenandoahHeap::NONE) { ! return cycle_mode; ! } ! ShenandoahHeap* heap = ShenandoahHeap::heap(); if (heap->has_forwarded_objects()) { // Cannot start partial if heap is not completely updated. ! return ShenandoahHeap::NONE; } size_t capacity = heap->capacity(); size_t used = heap->used(); size_t prev_used = heap->used_at_last_gc(); if (used < prev_used) { // Major collection must have happened, "used" data is unreliable, wait for update. ! return ShenandoahHeap::NONE; } size_t threshold = heap->capacity() * ShenandoahGenerationalYoungGenPercentage / 100; size_t allocated = used - prev_used;
*** 1142,1152 **** if (result) { log_info(gc,ergo)("%s", msg.buffer()); } else { log_trace(gc,ergo)("%s", msg.buffer()); } ! return result; } }; class ShenandoahLRUPartialHeuristics : public ShenandoahPartialHeuristics { public: --- 1262,1272 ---- if (result) { log_info(gc,ergo)("%s", msg.buffer()); } else { log_trace(gc,ergo)("%s", msg.buffer()); } ! return result ? ShenandoahHeap::MINOR : ShenandoahHeap::NONE; } }; class ShenandoahLRUPartialHeuristics : public ShenandoahPartialHeuristics { public:
*** 1157,1167 **** --- 1277,1292 ---- virtual const char* name() { return "LRU"; } virtual void choose_collection_set(ShenandoahCollectionSet* collection_set) { + if (!is_minor_gc()) { + return ShenandoahPartialHeuristics::choose_collection_set(collection_set); + } + ShenandoahHeap* heap = ShenandoahHeap::heap(); + ShenandoahTraversalGC* traversal_gc = heap->traversal_gc(); ShenandoahConnectionMatrix* matrix = heap->connection_matrix(); uint64_t alloc_seq_at_last_gc_start = heap->alloc_seq_at_last_gc_start(); size_t num_regions = heap->num_regions();
*** 1185,1198 **** size_t used = heap->used(); size_t prev_used = heap->used_at_last_gc(); guarantee(used >= prev_used, "Invariant"); size_t target = MIN2(ShenandoahHeapRegion::required_regions(used - prev_used), sorted_count); ! for (uint to_idx = 0; to_idx < num_regions; to_idx++) { ! ShenandoahHeapRegion* region = heap->get_region(to_idx); ! region->set_root(false); ! } uint count = 0; for (uint i = 0; (i < sorted_count) && (count < target); i++) { ShenandoahHeapRegion* contender = candidates[i]._region; if (contender->seqnum_last_alloc() >= alloc_seq_at_last_gc_start) { --- 1310,1322 ---- size_t used = heap->used(); size_t prev_used = heap->used_at_last_gc(); guarantee(used >= prev_used, "Invariant"); size_t target = MIN2(ShenandoahHeapRegion::required_regions(used - prev_used), sorted_count); ! ShenandoahHeapRegionSet* root_regions = traversal_gc->root_regions(); ! root_regions->clear(); ! uint count = 0; for (uint i = 0; (i < sorted_count) && (count < target); i++) { ShenandoahHeapRegion* contender = candidates[i]._region; if (contender->seqnum_last_alloc() >= alloc_seq_at_last_gc_start) {
*** 1206,1242 **** if (maybe_add_heap_region(contender, collection_set)) { count++; } for (uint f = 0; f < from_idx_count; f++) { ShenandoahHeapRegion* r = heap->get_region(_from_idxs[f]); ! if (!r->is_root()) { ! r->set_root(true); ! } } } } collection_set->update_region_status(); log_info(gc,ergo)("Regions: Max: " SIZE_FORMAT ", Target: " SIZE_FORMAT " (" SIZE_FORMAT "%%), In CSet: " SIZE_FORMAT, num_regions, target, ShenandoahLRUOldGenPercentage, collection_set->count()); } ! bool should_start_partial_gc() { ShenandoahHeap* heap = ShenandoahHeap::heap(); if (heap->has_forwarded_objects()) { // Cannot start partial if heap is not completely updated. ! return false; } size_t capacity = heap->capacity(); size_t used = heap->used(); size_t prev_used = heap->used_at_last_gc(); if (used < prev_used) { // Major collection must have happened, "used" data is unreliable, wait for update. ! return false; } // For now don't start until we are 40% full size_t allocated = used - prev_used; size_t threshold = heap->capacity() * ShenandoahLRUOldGenPercentage / 100; --- 1330,1370 ---- if (maybe_add_heap_region(contender, collection_set)) { count++; } for (uint f = 0; f < from_idx_count; f++) { ShenandoahHeapRegion* r = heap->get_region(_from_idxs[f]); ! root_regions->add_region_check_for_duplicates(r); } } } + filter_regions(); collection_set->update_region_status(); log_info(gc,ergo)("Regions: Max: " SIZE_FORMAT ", Target: " SIZE_FORMAT " (" SIZE_FORMAT "%%), In CSet: " SIZE_FORMAT, num_regions, target, ShenandoahLRUOldGenPercentage, collection_set->count()); } ! ShenandoahHeap::GCCycleMode should_start_traversal_gc() { ! ShenandoahHeap::GCCycleMode cycle_mode = ShenandoahPartialHeuristics::should_start_traversal_gc(); ! if (cycle_mode != ShenandoahHeap::NONE) { ! return cycle_mode; ! } ! ShenandoahHeap* heap = ShenandoahHeap::heap(); if (heap->has_forwarded_objects()) { // Cannot start partial if heap is not completely updated. ! return ShenandoahHeap::NONE; } size_t capacity = heap->capacity(); size_t used = heap->used(); size_t prev_used = heap->used_at_last_gc(); if (used < prev_used) { // Major collection must have happened, "used" data is unreliable, wait for update. ! return ShenandoahHeap::NONE; } // For now don't start until we are 40% full size_t allocated = used - prev_used; size_t threshold = heap->capacity() * ShenandoahLRUOldGenPercentage / 100;
*** 1252,1352 **** if (result) { log_info(gc,ergo)("%s", msg.buffer()); } else { log_trace(gc,ergo)("%s", msg.buffer()); } ! return result; ! } ! ! }; ! ! class ShenandoahTraversalHeuristics : public ShenandoahHeuristics { ! public: ! ShenandoahTraversalHeuristics() : ShenandoahHeuristics() { ! FLAG_SET_DEFAULT(UseShenandoahMatrix, false); ! FLAG_SET_DEFAULT(ShenandoahSATBBarrier, false); ! FLAG_SET_DEFAULT(ShenandoahConditionalSATBBarrier, false); ! FLAG_SET_DEFAULT(ShenandoahStoreValReadBarrier, false); ! FLAG_SET_DEFAULT(ShenandoahStoreValWriteBarrier, false); ! FLAG_SET_DEFAULT(ShenandoahStoreValEnqueueBarrier, true); ! FLAG_SET_DEFAULT(ShenandoahKeepAliveBarrier, false); ! FLAG_SET_DEFAULT(ShenandoahBarriersForConst, true); ! FLAG_SET_DEFAULT(ShenandoahWriteBarrierRB, false); ! FLAG_SET_DEFAULT(ShenandoahAllocImplicitLive, false); ! FLAG_SET_DEFAULT(ShenandoahAllowMixedAllocs, false); ! } ! ! virtual bool should_start_normal_gc() const { ! return false; ! } ! ! virtual bool is_experimental() { ! return true; ! } ! ! virtual bool is_diagnostic() { ! return false; ! } ! ! virtual bool can_do_traversal_gc() { ! return true; ! } ! ! virtual const char* name() { ! return "traversal"; ! } ! ! virtual void choose_collection_set(ShenandoahCollectionSet* collection_set) { ! ShenandoahHeap* heap = ShenandoahHeap::heap(); ! for (size_t i = 0; i < heap->num_regions(); i++) { ! ShenandoahHeapRegion* r = heap->get_region(i); ! assert(!r->is_root(), "must not be root region"); ! assert(!collection_set->is_in(r), "must not yet be in cset"); ! if (r->is_regular() && r->used() > 0) { ! size_t garbage_percent = r->garbage() * 100 / ShenandoahHeapRegion::region_size_bytes(); ! if (garbage_percent > ShenandoahGarbageThreshold) { ! collection_set->add_region(r); ! } ! } ! heap->set_next_top_at_mark_start(r->bottom(), r->top()); ! heap->set_complete_top_at_mark_start(r->bottom(), r->top()); // For debugging purposes ! r->clear_live_data(); ! } ! collection_set->update_region_status(); } - virtual bool should_start_traversal_gc() { - - ShenandoahHeap* heap = ShenandoahHeap::heap(); - - if (heap->has_forwarded_objects()) return false; - - double last_time_ms = (os::elapsedTime() - _last_cycle_end) * 1000; - bool periodic_gc = (last_time_ms > ShenandoahGuaranteedGCInterval); - if (periodic_gc) { - log_info(gc,ergo)("Periodic GC triggered. Time since last GC: %.0f ms, Guaranteed Interval: " UINTX_FORMAT " ms", - last_time_ms, ShenandoahGuaranteedGCInterval); - return true; - } - - size_t capacity = heap->capacity(); - size_t used = heap->used(); - return 100 - (used * 100 / capacity) < ShenandoahFreeThreshold; - } - - virtual void choose_collection_set_from_regiondata(ShenandoahCollectionSet* set, - RegionData* data, size_t data_size, - size_t free) { - ShouldNotReachHere(); - } }; - ShenandoahCollectorPolicy::ShenandoahCollectorPolicy() : _cycle_counter(0), _success_concurrent_gcs(0), - _success_partial_gcs(0), _success_degenerated_gcs(0), _success_full_gcs(0), _explicit_concurrent(0), _explicit_full(0), _alloc_failure_degenerated(0), --- 1380,1397 ---- if (result) { log_info(gc,ergo)("%s", msg.buffer()); } else { log_trace(gc,ergo)("%s", msg.buffer()); } ! return result ? ShenandoahHeap::MINOR : ShenandoahHeap::NONE; } }; ShenandoahCollectorPolicy::ShenandoahCollectorPolicy() : _cycle_counter(0), _success_concurrent_gcs(0), _success_degenerated_gcs(0), _success_full_gcs(0), _explicit_concurrent(0), _explicit_full(0), _alloc_failure_degenerated(0),
*** 1360,1370 **** initialize_all(); _tracer = new (ResourceObj::C_HEAP, mtGC) ShenandoahTracer(); if (ShenandoahGCHeuristics != NULL) { - _minor_heuristics = NULL; if (strcmp(ShenandoahGCHeuristics, "aggressive") == 0) { _heuristics = new ShenandoahAggressiveHeuristics(); } else if (strcmp(ShenandoahGCHeuristics, "static") == 0) { _heuristics = new ShenandoahStaticHeuristics(); } else if (strcmp(ShenandoahGCHeuristics, "adaptive") == 0) { --- 1405,1414 ----
*** 1372,1389 **** } else if (strcmp(ShenandoahGCHeuristics, "passive") == 0) { _heuristics = new ShenandoahPassiveHeuristics(); } else if (strcmp(ShenandoahGCHeuristics, "compact") == 0) { _heuristics = new ShenandoahCompactHeuristics(); } else if (strcmp(ShenandoahGCHeuristics, "connected") == 0) { ! _heuristics = new ShenandoahAdaptiveHeuristics(); ! _minor_heuristics = new ShenandoahPartialConnectedHeuristics(); } else if (strcmp(ShenandoahGCHeuristics, "generational") == 0) { ! _heuristics = new ShenandoahAdaptiveHeuristics(); ! _minor_heuristics = new ShenandoahGenerationalPartialHeuristics(); } else if (strcmp(ShenandoahGCHeuristics, "LRU") == 0) { ! _heuristics = new ShenandoahAdaptiveHeuristics(); ! _minor_heuristics = new ShenandoahLRUPartialHeuristics(); } else if (strcmp(ShenandoahGCHeuristics, "traversal") == 0) { _heuristics = new ShenandoahTraversalHeuristics(); } else { vm_exit_during_initialization("Unknown -XX:ShenandoahGCHeuristics option"); } --- 1416,1430 ---- } else if (strcmp(ShenandoahGCHeuristics, "passive") == 0) { _heuristics = new ShenandoahPassiveHeuristics(); } else if (strcmp(ShenandoahGCHeuristics, "compact") == 0) { _heuristics = new ShenandoahCompactHeuristics(); } else if (strcmp(ShenandoahGCHeuristics, "connected") == 0) { ! _heuristics = new ShenandoahPartialConnectedHeuristics(); } else if (strcmp(ShenandoahGCHeuristics, "generational") == 0) { ! _heuristics = new ShenandoahGenerationalPartialHeuristics(); } else if (strcmp(ShenandoahGCHeuristics, "LRU") == 0) { ! _heuristics = new ShenandoahLRUPartialHeuristics(); } else if (strcmp(ShenandoahGCHeuristics, "traversal") == 0) { _heuristics = new ShenandoahTraversalHeuristics(); } else { vm_exit_during_initialization("Unknown -XX:ShenandoahGCHeuristics option"); }
*** 1396,1435 **** if (_heuristics->is_experimental() && !UnlockExperimentalVMOptions) { vm_exit_during_initialization( err_msg("Heuristics \"%s\" is experimental, and must be enabled via -XX:+UnlockExperimentalVMOptions.", _heuristics->name())); } - if (_minor_heuristics != NULL && _minor_heuristics->is_diagnostic() && !UnlockDiagnosticVMOptions) { - vm_exit_during_initialization( - err_msg("Heuristics \"%s\" is diagnostic, and must be enabled via -XX:+UnlockDiagnosticVMOptions.", - _minor_heuristics->name())); - } - if (_minor_heuristics != NULL && _minor_heuristics->is_experimental() && !UnlockExperimentalVMOptions) { - vm_exit_during_initialization( - err_msg("Heuristics \"%s\" is experimental, and must be enabled via -XX:+UnlockExperimentalVMOptions.", - _minor_heuristics->name())); - } - if (ShenandoahConditionalSATBBarrier && ShenandoahSATBBarrier) { - vm_exit_during_initialization("Cannot use both ShenandoahSATBBarrier and ShenandoahConditionalSATBBarrier"); - } - if (ShenandoahStoreValWriteBarrier && ShenandoahStoreValReadBarrier) { - vm_exit_during_initialization("Cannot use both ShenandoahStoreValWriteBarrier and ShenandoahStoreValReadBarrier"); - } if (ShenandoahStoreValEnqueueBarrier && ShenandoahStoreValReadBarrier) { vm_exit_during_initialization("Cannot use both ShenandoahStoreValEnqueueBarrier and ShenandoahStoreValReadBarrier"); } - if (ShenandoahStoreValWriteBarrier && ShenandoahStoreValEnqueueBarrier) { - vm_exit_during_initialization("Cannot use both ShenandoahStoreValWriteBarrier and ShenandoahStoreValEnqueueBarrier"); - } - if (_minor_heuristics != NULL) { - log_info(gc, init)("Shenandoah heuristics: %s minor with %s major", - _minor_heuristics->name(), _heuristics->name()); - } else { log_info(gc, init)("Shenandoah heuristics: %s", _heuristics->name()); - } _heuristics->print_thresholds(); } else { ShouldNotReachHere(); } } --- 1437,1452 ----
*** 1461,1473 **** _heap_alignment = ShenandoahHeapRegion::region_size_bytes(); } void ShenandoahCollectorPolicy::post_heap_initialize() { _heuristics->initialize(); - if (_minor_heuristics != NULL) { - _minor_heuristics->initialize(); - } } void ShenandoahCollectorPolicy::record_explicit_to_concurrent() { _heuristics->record_explicit_gc(); _explicit_concurrent++; --- 1478,1487 ----
*** 1497,1510 **** void ShenandoahCollectorPolicy::record_success_concurrent() { _heuristics->record_success_concurrent(); _success_concurrent_gcs++; } - void ShenandoahCollectorPolicy::record_success_partial() { - _success_partial_gcs++; - } - void ShenandoahCollectorPolicy::record_success_degenerated() { _heuristics->record_success_degenerated(); _success_degenerated_gcs++; } --- 1511,1520 ----
*** 1520,1551 **** bool ShenandoahCollectorPolicy::should_degenerate_cycle() { return _heuristics->should_degenerate_cycle(); } bool ShenandoahCollectorPolicy::update_refs() { - if (_minor_heuristics != NULL && _minor_heuristics->update_refs()) { - return true; - } return _heuristics->update_refs(); } bool ShenandoahCollectorPolicy::should_start_update_refs() { - if (_minor_heuristics != NULL && _minor_heuristics->should_start_update_refs()) { - return true; - } return _heuristics->should_start_update_refs(); } void ShenandoahCollectorPolicy::record_peak_occupancy() { _heuristics->record_peak_occupancy(); } void ShenandoahCollectorPolicy::choose_collection_set(ShenandoahCollectionSet* collection_set, bool minor) { - if (minor) - _minor_heuristics->choose_collection_set(collection_set); - else _heuristics->choose_collection_set(collection_set); } bool ShenandoahCollectorPolicy::should_process_references() { return _heuristics->should_process_references(); --- 1530,1552 ----
*** 1561,1587 **** void ShenandoahCollectorPolicy::record_phase_time(ShenandoahPhaseTimings::Phase phase, double secs) { _heuristics->record_phase_time(phase, secs); } ! bool ShenandoahCollectorPolicy::should_start_partial_gc() { ! if (_minor_heuristics != NULL) { ! return _minor_heuristics->should_start_partial_gc(); ! } else { ! return false; // no minor heuristics -> no partial gc ! } ! } ! ! bool ShenandoahCollectorPolicy::can_do_partial_gc() { ! if (_minor_heuristics != NULL) { ! return _minor_heuristics->can_do_partial_gc(); ! } else { ! return false; // no minor heuristics -> no partial gc ! } ! } ! ! bool ShenandoahCollectorPolicy::should_start_traversal_gc() { return _heuristics->should_start_traversal_gc(); } bool ShenandoahCollectorPolicy::can_do_traversal_gc() { return _heuristics->can_do_traversal_gc(); --- 1562,1572 ---- void ShenandoahCollectorPolicy::record_phase_time(ShenandoahPhaseTimings::Phase phase, double secs) { _heuristics->record_phase_time(phase, secs); } ! ShenandoahHeap::GCCycleMode ShenandoahCollectorPolicy::should_start_traversal_gc() { return _heuristics->should_start_traversal_gc(); } bool ShenandoahCollectorPolicy::can_do_traversal_gc() { return _heuristics->can_do_traversal_gc();
*** 1609,1621 **** out->print_cr("under stop-the-world pause or result in stop-the-world Full GC. Increase heap size,"); out->print_cr("tune GC heuristics, set more aggressive pacing delay, or lower allocation rate"); out->print_cr("to avoid Degenerated and Full GC cycles."); out->cr(); - out->print_cr(SIZE_FORMAT_W(5) " successful partial concurrent GCs", _success_partial_gcs); - out->cr(); - out->print_cr(SIZE_FORMAT_W(5) " successful concurrent GCs", _success_concurrent_gcs); out->print_cr(" " SIZE_FORMAT_W(5) " invoked explicitly", _explicit_concurrent); out->cr(); out->print_cr(SIZE_FORMAT_W(5) " Degenerated GCs", _success_degenerated_gcs); --- 1594,1603 ----
< prev index next >