1/*
2 * Copyright 2013-present Facebook, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
19#include <folly/stats/MultiLevelTimeSeries.h>
20#include <glog/logging.h>
21
22namespace folly {
23
24template <typename VT, typename CT>
25MultiLevelTimeSeries<VT, CT>::MultiLevelTimeSeries(
26 size_t nBuckets,
27 size_t nLevels,
28 const Duration levelDurations[])
29 : cachedTime_(), cachedSum_(0), cachedCount_(0) {
30 CHECK_GT(nLevels, 0u);
31 CHECK(levelDurations);
32
33 levels_.reserve(nLevels);
34 for (size_t i = 0; i < nLevels; ++i) {
35 if (levelDurations[i] == Duration(0)) {
36 CHECK_EQ(i, nLevels - 1);
37 } else if (i > 0) {
38 CHECK(levelDurations[i - 1] < levelDurations[i]);
39 }
40 levels_.emplace_back(nBuckets, levelDurations[i]);
41 }
42}
43
44template <typename VT, typename CT>
45MultiLevelTimeSeries<VT, CT>::MultiLevelTimeSeries(
46 size_t nBuckets,
47 std::initializer_list<Duration> durations)
48 : cachedTime_(), cachedSum_(0), cachedCount_(0) {
49 CHECK_GT(durations.size(), 0u);
50
51 levels_.reserve(durations.size());
52 size_t i = 0;
53 Duration prev{0};
54 for (auto dur : durations) {
55 if (dur == Duration(0)) {
56 CHECK_EQ(i, durations.size() - 1);
57 } else if (i > 0) {
58 CHECK(prev < dur);
59 }
60 levels_.emplace_back(nBuckets, dur);
61 prev = dur;
62 i++;
63 }
64}
65
66template <typename VT, typename CT>
67void MultiLevelTimeSeries<VT, CT>::addValue(
68 TimePoint now,
69 const ValueType& val) {
70 addValueAggregated(now, val, 1);
71}
72
73template <typename VT, typename CT>
74void MultiLevelTimeSeries<VT, CT>::addValue(
75 TimePoint now,
76 const ValueType& val,
77 uint64_t times) {
78 addValueAggregated(now, val * ValueType(times), times);
79}
80
81template <typename VT, typename CT>
82void MultiLevelTimeSeries<VT, CT>::addValueAggregated(
83 TimePoint now,
84 const ValueType& total,
85 uint64_t nsamples) {
86 if (cachedTime_ != now) {
87 flush();
88 cachedTime_ = now;
89 }
90 cachedSum_ += total;
91 cachedCount_ += nsamples;
92}
93
94template <typename VT, typename CT>
95void MultiLevelTimeSeries<VT, CT>::update(TimePoint now) {
96 flush();
97 for (size_t i = 0; i < levels_.size(); ++i) {
98 levels_[i].update(now);
99 }
100}
101
102template <typename VT, typename CT>
103void MultiLevelTimeSeries<VT, CT>::flush() {
104 // update all the underlying levels
105 if (cachedCount_ > 0) {
106 for (size_t i = 0; i < levels_.size(); ++i) {
107 levels_[i].addValueAggregated(cachedTime_, cachedSum_, cachedCount_);
108 }
109 cachedCount_ = 0;
110 cachedSum_ = 0;
111 }
112}
113
114template <typename VT, typename CT>
115void MultiLevelTimeSeries<VT, CT>::clear() {
116 for (auto& level : levels_) {
117 level.clear();
118 }
119
120 cachedTime_ = TimePoint();
121 cachedSum_ = 0;
122 cachedCount_ = 0;
123}
124
125} // namespace folly
126