diff options
| author | Stefan Boberg <[email protected]> | 2021-09-27 00:17:45 +0200 |
|---|---|---|
| committer | Stefan Boberg <[email protected]> | 2021-09-27 00:17:45 +0200 |
| commit | bca8f116ed7a3ab484df62c15e9f49e0167e2b2f (patch) | |
| tree | 3e01bd4ef2fc060486681725e4106286961cc132 /zencore/include | |
| parent | Fixed up some internals for coding conventions (diff) | |
| download | zen-bca8f116ed7a3ab484df62c15e9f49e0167e2b2f.tar.xz zen-bca8f116ed7a3ab484df62c15e9f49e0167e2b2f.zip | |
stats: Completed Meter implementation
Diffstat (limited to 'zencore/include')
| -rw-r--r-- | zencore/include/zencore/stats.h | 60 |
1 files changed, 48 insertions, 12 deletions
diff --git a/zencore/include/zencore/stats.h b/zencore/include/zencore/stats.h index 7290fd914..0554f620d 100644 --- a/zencore/include/zencore/stats.h +++ b/zencore/include/zencore/stats.h @@ -12,30 +12,44 @@ template<typename T> class Gauge { public: - Gauge() : m_value{0} {} + Gauge() : m_Value{0} {} + + T Value() const { return m_Value; } + void SetValue(T Value) { m_Value = Value; } private: - T m_value; + std::atomic<T> m_Value; }; +/** Stats counter + * + * A counter is modified by adding or subtracting a value from a current value. + * This would typically be used to track number of requests in flight, number + * of active jobs etc + * + */ class Counter { public: inline void SetValue(uint64_t Value) { m_count = Value; } inline uint64_t Value() const { return m_count; } - inline void Increment(int64_t AddValue) { m_count += AddValue; } - inline void Decrement(int64_t SubValue) { m_count -= SubValue; } - inline void Clear() { m_count = 0; } + inline void Increment(int64_t AddValue) { m_count.fetch_add(AddValue); } + inline void Decrement(int64_t SubValue) { m_count.fetch_sub(SubValue); } + inline void Clear() { m_count.store(0, std::memory_order_release); } private: - std::atomic_uint64_t m_count{0}; + std::atomic<uint64_t> m_count{0}; }; -/// <summary> -/// Exponential Weighted Moving Average -/// </summary> -class EWMA +/** Exponential Weighted Moving Average + + This is very raw, to use as little state as possible. If we + want to use this more broadly in user code we should perhaps + add a more user-friendly wrapper + */ + +class RawEWMA { public: /// <summary> @@ -49,16 +63,38 @@ public: double Rate() const; private: - double m_rate = 0; + std::atomic<double> m_Rate = 0; }; /// <summary> -/// Tracks rate of events over time (i.e requests/sec) +/// Tracks rate of events over time (i.e requests/sec), using +/// exponential moving averages /// </summary> class Meter { public: + Meter(); + ~Meter(); + + double Rate1(); // One-minute rate + double Rate5(); // Five-minute rate + double Rate15(); // Fifteen-minute rate + double MeanRate(); // Mean rate since instantiation of this meter + void Mark(uint64_t Count = 1); // Register one or more events + private: + std::atomic<uint64_t> m_TotalCount{0}; // Accumulator counting number of marks since beginning + std::atomic<uint64_t> m_PendingCount{0}; // Pending EWMA update accumulator + std::atomic<uint64_t> m_StartTick{0}; // Time this was instantiated (for mean) + std::atomic<uint64_t> m_LastTick{0}; // Timestamp of last EWMA tick + std::atomic<int64_t> m_Remain{0}; // Tracks the "modulo" of tick time + bool m_IsFirstTick = true; + RawEWMA m_RateM1; + RawEWMA m_RateM5; + RawEWMA m_RateM15; + + void TickIfNecessary(); + void Tick(); }; extern void stats_forcelink(); |