summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrobot-piglet <[email protected]>2023-10-11 11:11:55 +0300
committerrobot-piglet <[email protected]>2023-10-11 11:43:57 +0300
commit5358119d432f0b81ccf781e8c0f5bd2e5fc5bce9 (patch)
tree2a33e31eceef7e828257719d2a5e5c6b9a51c150
parent137e73f0a182b6bcd71afc9c124f1ea747bf3e46 (diff)
Intermediate changes
-rw-r--r--yt/yt/core/misc/moving_average-inl.h67
-rw-r--r--yt/yt/core/misc/moving_average.h38
-rw-r--r--yt/yt/core/misc/unittests/moving_average_ut.cpp70
-rw-r--r--yt/yt/core/misc/unittests/ya.make1
4 files changed, 176 insertions, 0 deletions
diff --git a/yt/yt/core/misc/moving_average-inl.h b/yt/yt/core/misc/moving_average-inl.h
new file mode 100644
index 00000000000..2dcbd981859
--- /dev/null
+++ b/yt/yt/core/misc/moving_average-inl.h
@@ -0,0 +1,67 @@
+#ifndef MOVING_AVERAGE_INL_H_
+#error "Direct inclusion of this file is not allowed, include moving_average.h"
+// For the sake of sane code completion.
+#include "moving_average.h"
+#endif
+
+namespace NYT {
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <class TValue>
+TMovingAverage<TValue>::TMovingAverage(int windowSize)
+{
+ SetWindowSize(windowSize);
+}
+
+template <class TValue>
+void TMovingAverage<TValue>::AddValue(TValue value)
+{
+ Total_ += value;
+ Values_.push(std::move(value));
+
+ RemoveOldValues();
+}
+
+template <class TValue>
+std::optional<TValue> TMovingAverage<TValue>::GetAverage() const
+{
+ if (Values_.empty()) {
+ return {};
+ }
+
+ return Total_ / std::ssize(Values_);
+}
+
+template <class TValue>
+void TMovingAverage<TValue>::SetWindowSize(int windowSize)
+{
+ YT_VERIFY(windowSize >= 0);
+
+ WindowSize_ = windowSize;
+
+ RemoveOldValues();
+}
+
+template <class TValue>
+void TMovingAverage<TValue>::Reset()
+{
+ while (!Values_.empty()) {
+ Values_.pop();
+ }
+
+ Total_ = {};
+}
+
+template <class TValue>
+void TMovingAverage<TValue>::RemoveOldValues()
+{
+ while (std::ssize(Values_) > WindowSize_) {
+ Total_ -= Values_.front();
+ Values_.pop();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT
diff --git a/yt/yt/core/misc/moving_average.h b/yt/yt/core/misc/moving_average.h
new file mode 100644
index 00000000000..f32e34a153c
--- /dev/null
+++ b/yt/yt/core/misc/moving_average.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "public.h"
+
+namespace NYT {
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <class TValue>
+class TMovingAverage
+{
+public:
+ TMovingAverage() = default;
+ explicit TMovingAverage(int windowSize);
+
+ void AddValue(TValue value);
+
+ std::optional<TValue> GetAverage() const;
+
+ void SetWindowSize(int windowSize);
+
+ void Reset();
+
+private:
+ int WindowSize_ = 0;
+ std::queue<TValue> Values_;
+ TValue Total_{};
+
+ void RemoveOldValues();
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace NYT
+
+#define MOVING_AVERAGE_INL_H_
+#include "moving_average-inl.h"
+#undef MOVING_AVERAGE_INL_H_
diff --git a/yt/yt/core/misc/unittests/moving_average_ut.cpp b/yt/yt/core/misc/unittests/moving_average_ut.cpp
new file mode 100644
index 00000000000..8c2c8713586
--- /dev/null
+++ b/yt/yt/core/misc/unittests/moving_average_ut.cpp
@@ -0,0 +1,70 @@
+#include <yt/yt/core/test_framework/framework.h>
+
+#include <yt/yt/core/misc/moving_average.h>
+
+namespace NYT {
+namespace {
+
+////////////////////////////////////////////////////////////////////////////////
+
+TEST(TMovingAverageTest, Empty)
+{
+ TMovingAverage<int> movingAverage;
+ EXPECT_FALSE(movingAverage.GetAverage());
+
+ movingAverage.AddValue(0);
+ EXPECT_FALSE(movingAverage.GetAverage());
+}
+
+TEST(TMovingAverageTest, Reset)
+{
+ TMovingAverage<int> movingAverage(3);
+ EXPECT_FALSE(movingAverage.GetAverage());
+
+ movingAverage.AddValue(0);
+ movingAverage.AddValue(1);
+ movingAverage.AddValue(2);
+ EXPECT_EQ(1, movingAverage.GetAverage());
+
+ movingAverage.Reset();
+ EXPECT_FALSE(movingAverage.GetAverage());
+}
+
+TEST(TMovingAverageTest, SimpleInt)
+{
+ TMovingAverage<int> movingAverage(3);
+ EXPECT_FALSE(movingAverage.GetAverage());
+
+ movingAverage.AddValue(0);
+ movingAverage.AddValue(1);
+ for (int i = 1; i < 10; ++i) {
+ movingAverage.AddValue(i + 1);
+ EXPECT_EQ(i, movingAverage.GetAverage());
+ }
+
+ movingAverage.SetWindowSize(1);
+ EXPECT_EQ(10, movingAverage.GetAverage());
+
+ movingAverage.SetWindowSize(2);
+ EXPECT_EQ(10, movingAverage.GetAverage());
+
+ movingAverage.AddValue(20);
+ movingAverage.AddValue(30);
+ EXPECT_EQ(25, movingAverage.GetAverage());
+}
+
+TEST(TMovingAverageTest, SimpleDouble)
+{
+ TMovingAverage<double> movingAverage(100);
+ EXPECT_FALSE(movingAverage.GetAverage());
+
+ for (int i = 0; i < 1000; ++i) {
+ movingAverage.AddValue(i);
+ }
+ EXPECT_EQ(949.5, movingAverage.GetAverage());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+} // namespace
+} // namespace NYT
diff --git a/yt/yt/core/misc/unittests/ya.make b/yt/yt/core/misc/unittests/ya.make
index 0de99de730d..fae325df753 100644
--- a/yt/yt/core/misc/unittests/ya.make
+++ b/yt/yt/core/misc/unittests/ya.make
@@ -45,6 +45,7 @@ SRCS(
lru_cache_ut.cpp
maybe_inf_ut.cpp
memory_tag_ut.cpp
+ moving_average_ut.cpp
mpsc_fair_share_queue_ut.cpp
mpsc_stack_ut.cpp
mpsc_queue_ut.cpp