Commit 59791afd authored by Marc Celani's avatar Marc Celani Committed by Facebook Github Bot

Create a new SlidingWindow data structure

Summary: Creates a new SlidingWindow data structure for general purpose use in stats code.

Reviewed By: anakryiko

Differential Revision: D7597047

fbshipit-source-id: 227438055029c2bacb5edf2943ebc9cc66fdfe36
parent d25334fb
...@@ -632,6 +632,7 @@ if (BUILD_TESTS) ...@@ -632,6 +632,7 @@ if (BUILD_TESTS)
DIRECTORY stats/test/ DIRECTORY stats/test/
TEST histogram_test SOURCES HistogramTest.cpp TEST histogram_test SOURCES HistogramTest.cpp
TEST sliding_window_test SOURCES SlidingWindowTest.cpp
TEST tdigest_test SOURCES TDigestTest.cpp TEST tdigest_test SOURCES TDigestTest.cpp
TEST timeseries_histogram_test SOURCES TimeseriesHistogramTest.cpp TEST timeseries_histogram_test SOURCES TimeseriesHistogramTest.cpp
TEST timeseries_test SOURCES TimeSeriesTest.cpp TEST timeseries_test SOURCES TimeSeriesTest.cpp
......
...@@ -439,6 +439,8 @@ nobase_follyinclude_HEADERS = \ ...@@ -439,6 +439,8 @@ nobase_follyinclude_HEADERS = \
ssl/detail/OpenSSLThreading.h \ ssl/detail/OpenSSLThreading.h \
ssl/detail/SSLSessionImpl.h \ ssl/detail/SSLSessionImpl.h \
stats/detail/Bucket.h \ stats/detail/Bucket.h \
stats/detail/SlidingWindow-defs.h \
stats/detail/SlidingWindow.h \
stats/BucketedTimeSeries-defs.h \ stats/BucketedTimeSeries-defs.h \
stats/BucketedTimeSeries.h \ stats/BucketedTimeSeries.h \
stats/Histogram-defs.h \ stats/Histogram-defs.h \
......
/*
* Copyright 2018-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <folly/stats/detail/SlidingWindow.h>
#include <algorithm>
namespace folly {
namespace detail {
template <typename BucketT>
SlidingWindow<BucketT>::SlidingWindow(
Function<BucketT(void)> fn,
size_t numBuckets)
: fn_(std::move(fn)), curHead_(0) {
buckets_.reserve(numBuckets);
for (size_t i = 0; i < numBuckets; ++i) {
buckets_.push_back(fn_());
}
std::reverse(buckets_.begin(), buckets_.end());
}
template <typename BucketT>
SlidingWindow<BucketT>::SlidingWindow(SlidingWindow<BucketT>&& rhs)
: fn_(std::move(rhs.fn_)),
buckets_(std::move(rhs.buckets_)),
curHead_(rhs.curHead_) {}
template <typename BucketT>
std::vector<BucketT> SlidingWindow<BucketT>::get() const {
std::vector<BucketT> buckets;
buckets.reserve(buckets_.size());
buckets.insert(buckets.end(), buckets_.begin() + curHead_, buckets_.end());
buckets.insert(buckets.end(), buckets_.begin(), buckets_.begin() + curHead_);
return buckets;
}
template <typename BucketT>
BucketT SlidingWindow<BucketT>::slide(size_t nBuckets) {
nBuckets = std::min(nBuckets, buckets_.size());
for (size_t i = 0; i < nBuckets; ++i) {
if (curHead_ == 0) {
curHead_ = buckets_.size() - 1;
} else {
curHead_--;
}
buckets_[curHead_] = fn_();
}
return buckets_[curHead_];
}
} // namespace detail
} // namespace folly
/*
* Copyright 2018-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <cstddef>
#include <vector>
#include <folly/Function.h>
namespace folly {
namespace detail {
/*
* This class represents a sliding window that can be used to track stats over
* time. Buckets are dropped and new ones are added with the slide() method.
* New buckets are created with the constructor function given at construction.
*/
template <typename BucketT>
class SlidingWindow {
public:
SlidingWindow(Function<BucketT(void)> fn, size_t numBuckets);
SlidingWindow(SlidingWindow&& rhs);
std::vector<BucketT> get() const;
/*
* Slides the SlidingWindow by nBuckets, inserting new buckets using the
* Function given during construction. Returns the new first bucket.
*/
BucketT slide(size_t nBuckets);
private:
Function<BucketT(void)> fn_;
std::vector<BucketT> buckets_;
size_t curHead_;
};
} // namespace detail
} // namespace folly
...@@ -5,12 +5,16 @@ ldadd = $(top_builddir)/test/libfollytestmain.la ...@@ -5,12 +5,16 @@ ldadd = $(top_builddir)/test/libfollytestmain.la
TESTS = \ TESTS = \
histogram_test \ histogram_test \
sliding_window_test \
tdigest_test tdigest_test
TESTS = $(check_PROGRAMS) check_PROGRAMS = $(TESTS)
histogram_test_SOURCES = HistogramTest.cpp histogram_test_SOURCES = HistogramTest.cpp
histogram_test_LDADD = $(ldadd) histogram_test_LDADD = $(ldadd)
sliding_window_test_SOURCES = SlidingWindowTest.cpp
sliding_window_test_LDADD = $(ldadd)
tdigest_test_SOURCES = TDigestTest.cpp tdigest_test_SOURCES = TDigestTest.cpp
tdigest_test_LDADD = $(ldadd) tdigest_test_LDADD = $(ldadd)
/*
* Copyright 2018-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/stats/detail/SlidingWindow-defs.h>
#include <folly/portability/GTest.h>
using namespace folly;
using namespace folly::detail;
class SlidingWindowTest : public ::testing::Test {
protected:
std::unique_ptr<SlidingWindow<size_t>> slidingWindow;
size_t curWindow = 0;
void SetUp() override {
slidingWindow = std::make_unique<SlidingWindow<size_t>>(
[&]() { return curWindow++; }, 60);
}
};
TEST_F(SlidingWindowTest, Constructor) {
auto buckets = slidingWindow->get();
EXPECT_EQ(60, buckets.size());
for (size_t i = 0; i < 60; ++i) {
EXPECT_EQ(60 - i - 1, buckets[i]);
}
}
TEST_F(SlidingWindowTest, SlideZero) {
slidingWindow->slide(0);
auto buckets = slidingWindow->get();
EXPECT_EQ(60, buckets.size());
for (size_t i = 0; i < 60; ++i) {
EXPECT_EQ(60 - i - 1, buckets[i]);
}
}
TEST_F(SlidingWindowTest, SlideLessThanFullAmount) {
slidingWindow->slide(5);
auto buckets = slidingWindow->get();
EXPECT_EQ(60, buckets.size());
for (size_t i = 0; i < 60; ++i) {
EXPECT_EQ(65 - i - 1, buckets[i]);
}
}
TEST_F(SlidingWindowTest, SlideMoreThanFullAmount) {
slidingWindow->slide(60);
auto buckets = slidingWindow->get();
EXPECT_EQ(60, buckets.size());
for (size_t i = 0; i < 60; ++i) {
EXPECT_EQ(120 - i - 1, buckets[i]);
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment