diff options
| author | Stefan Boberg <[email protected]> | 2021-09-29 22:26:02 +0200 |
|---|---|---|
| committer | Stefan Boberg <[email protected]> | 2021-09-29 22:26:02 +0200 |
| commit | 60dcdd0a7c1c8184f60444d92bae39ea3273ec8f (patch) | |
| tree | 0a137d5b7fa9b28b866253a86994d0a9f8c85583 /zencore/include | |
| parent | filesystem: Fixed issue with FindClose potentially closing an invalid handle (diff) | |
| download | zen-60dcdd0a7c1c8184f60444d92bae39ea3273ec8f.tar.xz zen-60dcdd0a7c1c8184f60444d92bae39ea3273ec8f.zip | |
stats: added Histogram, UniformSample and SampleSnapshot
Diffstat (limited to 'zencore/include')
| -rw-r--r-- | zencore/include/zencore/stats.h | 88 |
1 files changed, 85 insertions, 3 deletions
diff --git a/zencore/include/zencore/stats.h b/zencore/include/zencore/stats.h index 0554f620d..7665d0cf5 100644 --- a/zencore/include/zencore/stats.h +++ b/zencore/include/zencore/stats.h @@ -2,11 +2,12 @@ #pragma once -#include <atomic> -#include <type_traits> #include "zencore.h" -namespace zen { +#include <atomic> +#include <random> + +namespace zen::metrics { template<typename T> class Gauge @@ -97,6 +98,87 @@ private: void Tick(); }; +/** Moment-in-time snapshot of a distribution + */ +class SampleSnapshot +{ +public: + SampleSnapshot(std::vector<double>&& Values); + ~SampleSnapshot(); + + uint32_t Size() const { return (uint32_t)m_Values.size(); } + double GetQuantileValue(double Quantile); + double GetMedian() { return GetQuantileValue(0.5); } + double Get75Percentile() { return GetQuantileValue(0.75); } + double Get95Percentile() { return GetQuantileValue(0.95); } + double Get98Percentile() { return GetQuantileValue(0.98); } + double Get99Percentile() { return GetQuantileValue(0.99); } + double Get999Percentile() { return GetQuantileValue(0.999); } + const std::vector<double>& GetValues() const; + +private: + std::vector<double> m_Values; +}; + +/** Randomly selects samples from a stream. Uses Vitter's + Algorithm R to produce a statistically representative sample. + + http://www.cs.umd.edu/~samir/498/vitter.pdf - Random Sampling with a Reservoir + */ + +class UniformSample +{ +public: + UniformSample(uint32_t ReservoirSize); + ~UniformSample(); + + void Clear(); + uint32_t Size() const; + void Update(int64_t Value); + SampleSnapshot Snapshot() const; + + template<std::invocable<int64_t> T> + void IterateValues(T Callback) const + { + for (const auto& Value : m_Values) + { + Callback(Value); + } + } + +private: + std::atomic<uint64_t> m_SampleCounter{0}; + std::vector<std::atomic<int64_t>> m_Values; +}; + +/** Track (probabilistic) sample distribution along with min/max + */ +class Histogram +{ +public: + Histogram(int32_t SampleCount = 1028); + ~Histogram(); + + void Clear(); + void Update(int64_t Value); + int64_t Max() const; + int64_t Min() const; + double Mean() const; + uint64_t Count() const; + SampleSnapshot Snapshot() const { return m_Sample.Snapshot(); } + +private: + UniformSample m_Sample; + std::atomic<int64_t> m_Min{0}; + std::atomic<int64_t> m_Max{0}; + std::atomic<int64_t> m_Sum{0}; + std::atomic<int64_t> m_Count{0}; +}; + +} // namespace zen::metrics + +namespace zen { + extern void stats_forcelink(); } // namespace zen |