aboutsummaryrefslogtreecommitdiff
path: root/zencore/include
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2021-09-27 00:17:45 +0200
committerStefan Boberg <[email protected]>2021-09-27 00:17:45 +0200
commitbca8f116ed7a3ab484df62c15e9f49e0167e2b2f (patch)
tree3e01bd4ef2fc060486681725e4106286961cc132 /zencore/include
parentFixed up some internals for coding conventions (diff)
downloadzen-bca8f116ed7a3ab484df62c15e9f49e0167e2b2f.tar.xz
zen-bca8f116ed7a3ab484df62c15e9f49e0167e2b2f.zip
stats: Completed Meter implementation
Diffstat (limited to 'zencore/include')
-rw-r--r--zencore/include/zencore/stats.h60
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();