From 2593dbcaa677b190e564fb394446c2e91adb388d Mon Sep 17 00:00:00 2001 From: Sergei Trifonov Date: Mon, 18 Jul 2022 12:21:44 +0200 Subject: [PATCH] reuse Common/ExponentiallySmoothedCounter.h --- src/Common/EventRateMeter.h | 66 ++++++++++++------------------- src/Common/ProgressIndication.cpp | 4 +- src/Common/ProgressIndication.h | 2 +- 3 files changed, 29 insertions(+), 43 deletions(-) diff --git a/src/Common/EventRateMeter.h b/src/Common/EventRateMeter.h index b8582585e4b..a32324de63c 100644 --- a/src/Common/EventRateMeter.h +++ b/src/Common/EventRateMeter.h @@ -2,9 +2,14 @@ #include #include + +#include + #include #include #include +#include + namespace DB { @@ -12,42 +17,23 @@ namespace DB /// Event count measurement with exponential smoothing intended for computing time derivatives class EventRateMeter { public: - explicit EventRateMeter(UInt64 period_, UInt64 resolution = 1000) - : period(std::max(period_, 1ul)) - , step(std::max(period / resolution, 1ul)) - , decay(1.0 - 1.0 / resolution) - {} + explicit EventRateMeter(double now, double period_) + : period(period_) + , half_decay_time(period * std::numbers::ln2) // for `ExponentiallySmoothedAverage::sumWeights()` to be equal to `1/period` + { + reset(now); + } /// Add `count` events happened at `now` instant. /// Previous events that are older than `period` from `now` will be forgotten /// in a way to keep average event rate the same, using exponential smoothing. /// NOTE: Adding events into distant past (further than `period`) must be avoided. - void add(UInt64 now, UInt64 count = 1) + void add(double now, double count) { - if (unlikely(end == 0)) - { - // Initialization during the first call - if (start == 0) - start = now; - end = start + period; - } - else if (now > end) - { - // Compute number of steps we have to move for `now <= end` to became true - UInt64 steps = (now - end + step - 1) / step; - end += steps * step; - assert(now <= end); - - // Forget old events, assuming all events are distributed evenly throughout whole `period`. - // This assumption leads to exponential decay in case no new events will come. - if (steps == 1) - events *= decay; - else - events *= std::pow(decay, steps); - } - - // Add new events - events += count; + if (now - period <= start) // precise counting mode + events = ExponentiallySmoothedAverage(events.value + count, now); + else // exponential smoothing mode + events.add(count, now, half_decay_time); } /// Compute average event rate thoughout `[now - period, now]` period. @@ -58,23 +44,23 @@ public: add(now, 0); if (unlikely(now <= start)) return 0; - return double(events) / std::min(period, now - start); + if (now - period <= start) // precise counting mode + return events.value / (now - start); + else // exponential smoothing mode + return events.get(half_decay_time); // equals to `events.value / period` } - void reset(UInt64 now) + void reset(double now) { - events = 0; start = now; - end = 0; + events = ExponentiallySmoothedAverage(); } private: - const UInt64 period; - const UInt64 step; - const double decay; - double events = 0; // Estimated number of events in [end - period, end] range - UInt64 start = 0; // Instant in past without events before it; when measurement started or reset - UInt64 end = 0; // Instant in future to start decay; moving in steps + const double period; + const double half_decay_time; + double start; // Instant in past without events before it; when measurement started or reset + ExponentiallySmoothedAverage events; // Estimated number of events in the last `period` }; } diff --git a/src/Common/ProgressIndication.cpp b/src/Common/ProgressIndication.cpp index 2b4b5d9ade9..8ca1612e916 100644 --- a/src/Common/ProgressIndication.cpp +++ b/src/Common/ProgressIndication.cpp @@ -56,7 +56,7 @@ void ProgressIndication::resetProgress() write_progress_on_update = false; { std::lock_guard lock(profile_events_mutex); - cpu_usage_meter.reset(clock_gettime_ns()); + cpu_usage_meter.reset(static_cast(clock_gettime_ns())); thread_data.clear(); } } @@ -93,7 +93,7 @@ void ProgressIndication::updateThreadEventData(HostToThreadTimesMap & new_thread total_cpu_ns += aggregateCPUUsageNs(new_host_map.second); thread_data[new_host_map.first] = std::move(new_host_map.second); } - cpu_usage_meter.add(clock_gettime_ns(), total_cpu_ns); + cpu_usage_meter.add(static_cast(clock_gettime_ns()), total_cpu_ns); } size_t ProgressIndication::getUsedThreadsCount() const diff --git a/src/Common/ProgressIndication.h b/src/Common/ProgressIndication.h index 6ff89294475..588a31beca7 100644 --- a/src/Common/ProgressIndication.h +++ b/src/Common/ProgressIndication.h @@ -91,7 +91,7 @@ private: bool write_progress_on_update = false; - EventRateMeter cpu_usage_meter{3'000'000'000 /*ns*/}; // average cpu utilization last 3 second + EventRateMeter cpu_usage_meter{static_cast(clock_gettime_ns()), 3'000'000'000 /*ns*/}; // average cpu utilization last 3 second HostToThreadTimesMap thread_data; /// In case of all of the above: /// - clickhouse-local