--- old/src/hotspot/share/gc/z/zDirector.cpp 2019-11-18 08:18:54.065147042 +0100 +++ new/src/hotspot/share/gc/z/zDirector.cpp 2019-11-18 08:18:53.345123452 +0100 @@ -75,7 +75,7 @@ // duration, which is needed by the other rules. const size_t max_capacity = ZHeap::heap()->soft_max_capacity(); const size_t used = ZHeap::heap()->used(); - const double used_threshold_percent = (ZStatCycle::ncycles() + 1) * 0.1; + const double used_threshold_percent = (ZStatCycle::nwarmup_cycles() + 1) * 0.1; const size_t used_threshold = max_capacity * used_threshold_percent; log_debug(gc, director)("Rule: Warmup %.0f%%, Used: " SIZE_FORMAT "MB, UsedThreshold: " SIZE_FORMAT "MB", @@ -85,7 +85,7 @@ } bool ZDirector::rule_allocation_rate() const { - if (ZStatCycle::is_first()) { + if (!ZStatCycle::is_normalized_duration_trustable()) { // Rule disabled return false; } --- old/src/hotspot/share/gc/z/zDriver.cpp 2019-11-18 08:18:54.907174628 +0100 +++ new/src/hotspot/share/gc/z/zDriver.cpp 2019-11-18 08:18:54.249153070 +0100 @@ -250,17 +250,11 @@ case GCCause::_z_allocation_stall: case GCCause::_z_proactive: case GCCause::_z_high_usage: + case GCCause::_metadata_GC_threshold: // Start asynchronous GC _gc_cycle_port.send_async(cause); break; - case GCCause::_metadata_GC_threshold: - // Start asynchronous GC, but only if the GC is warm - if (ZStatCycle::is_warm()) { - _gc_cycle_port.send_async(cause); - } - break; - case GCCause::_gc_locker: // Restart VM operation previously blocked by the GC locker _gc_locker_port.signal(); @@ -352,13 +346,15 @@ class ZDriverGCScope : public StackObj { private: - GCIdMark _gc_id; - GCCauseSetter _gc_cause_setter; - ZStatTimer _timer; + GCIdMark _gc_id; + GCCause::Cause _gc_cause; + GCCauseSetter _gc_cause_setter; + ZStatTimer _timer; public: ZDriverGCScope(GCCause::Cause cause) : _gc_id(), + _gc_cause(cause), _gc_cause_setter(ZCollectedHeap::heap(), cause), _timer(ZPhaseCycle) { // Update statistics @@ -371,7 +367,7 @@ (double)ZHeap::heap()->nconcurrent_no_boost_worker_threads(); // Update statistics - ZStatCycle::at_end(boost_factor); + ZStatCycle::at_end(_gc_cause, boost_factor); // Update data used by soft reference policy Universe::update_heap_info_at_gc(); --- old/src/hotspot/share/gc/z/zStat.cpp 2019-11-18 08:18:55.807204116 +0100 +++ new/src/hotspot/share/gc/z/zStat.cpp 2019-11-18 08:18:55.081180329 +0100 @@ -1024,7 +1024,7 @@ // // Stat cycle // -uint64_t ZStatCycle::_ncycles = 0; +uint64_t ZStatCycle::_nwarmup_cycles = 0; Ticks ZStatCycle::_start_of_last; Ticks ZStatCycle::_end_of_last; NumberSeq ZStatCycle::_normalized_duration(0.3 /* alpha */); @@ -1033,9 +1033,12 @@ _start_of_last = Ticks::now(); } -void ZStatCycle::at_end(double boost_factor) { +void ZStatCycle::at_end(GCCause::Cause cause, double boost_factor) { _end_of_last = Ticks::now(); - _ncycles++; + + if (cause == GCCause::_z_warmup) { + _nwarmup_cycles++; + } // Calculate normalized cycle duration. The measured duration is // normalized using the boost factor to avoid artificial deflation @@ -1045,16 +1048,18 @@ _normalized_duration.add(normalized_duration); } -bool ZStatCycle::is_first() { - return _ncycles == 0; +bool ZStatCycle::is_warm() { + return _nwarmup_cycles >= 3; } -bool ZStatCycle::is_warm() { - return _ncycles >= 3; +uint64_t ZStatCycle::nwarmup_cycles() { + return _nwarmup_cycles; } -uint64_t ZStatCycle::ncycles() { - return _ncycles; +bool ZStatCycle::is_normalized_duration_trustable() { + // The normalized duration is considered trustable if we have + // completed at least one warmup cycle + return _nwarmup_cycles > 0; } const AbsSeq& ZStatCycle::normalized_duration() { @@ -1062,8 +1067,8 @@ } double ZStatCycle::time_since_last() { - if (_ncycles == 0) { - // Return time since VM start-up + if (_end_of_last.value() == 0) { + // No end recorded yet, return time since VM start return os::elapsedTime(); } --- old/src/hotspot/share/gc/z/zStat.hpp 2019-11-18 08:18:56.629231048 +0100 +++ new/src/hotspot/share/gc/z/zStat.hpp 2019-11-18 08:18:55.992210177 +0100 @@ -25,6 +25,7 @@ #define SHARE_GC_Z_ZSTAT_HPP #include "gc/shared/concurrentGCThread.hpp" +#include "gc/shared/gcCause.hpp" #include "gc/shared/gcTimer.hpp" #include "gc/z/zMetronome.hpp" #include "logging/logHandle.hpp" @@ -365,19 +366,21 @@ // class ZStatCycle : public AllStatic { private: - static uint64_t _ncycles; + static uint64_t _nwarmup_cycles; static Ticks _start_of_last; static Ticks _end_of_last; static NumberSeq _normalized_duration; public: static void at_start(); - static void at_end(double boost_factor); + static void at_end(GCCause::Cause cause, double boost_factor); - static bool is_first(); static bool is_warm(); - static uint64_t ncycles(); + static uint64_t nwarmup_cycles(); + + static bool is_normalized_duration_trustable(); static const AbsSeq& normalized_duration(); + static double time_since_last(); };