diff options
| author | robot-piglet <[email protected]> | 2023-10-11 11:11:55 +0300 |
|---|---|---|
| committer | robot-piglet <[email protected]> | 2023-10-11 11:43:57 +0300 |
| commit | 5358119d432f0b81ccf781e8c0f5bd2e5fc5bce9 (patch) | |
| tree | 2a33e31eceef7e828257719d2a5e5c6b9a51c150 | |
| parent | 137e73f0a182b6bcd71afc9c124f1ea747bf3e46 (diff) | |
Intermediate changes
| -rw-r--r-- | yt/yt/core/misc/moving_average-inl.h | 67 | ||||
| -rw-r--r-- | yt/yt/core/misc/moving_average.h | 38 | ||||
| -rw-r--r-- | yt/yt/core/misc/unittests/moving_average_ut.cpp | 70 | ||||
| -rw-r--r-- | yt/yt/core/misc/unittests/ya.make | 1 |
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 |
