1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
2 // This source code is licensed under the BSD-style license found in the
3 // LICENSE file in the root directory of this source tree. An additional grant
4 // of patent rights can be found in the PATENTS file in the same directory.
8 #include "monitoring/histogram.h"
9 #include "monitoring/histogram_windowing.h"
10 #include "util/testharness.h"
14 class HistogramTest
: public testing::Test
{};
17 const double kIota
= 0.1;
18 const HistogramBucketMapper bucketMapper
;
19 Env
* env
= Env::Default();
22 void PopulateHistogram(Histogram
& histogram
,
23 uint64_t low
, uint64_t high
, uint64_t loop
= 1) {
24 for (; loop
> 0; loop
--) {
25 for (uint64_t i
= low
; i
<= high
; i
++) {
31 void BasicOperation(Histogram
& histogram
) {
32 PopulateHistogram(histogram
, 1, 100, 10);
35 histogram
.Data(&data
);
37 ASSERT_LE(fabs(histogram
.Percentile(100.0) - 100.0), kIota
);
38 ASSERT_LE(fabs(data
.percentile99
- 99.0), kIota
);
39 ASSERT_LE(fabs(data
.percentile95
- 95.0), kIota
);
40 ASSERT_LE(fabs(data
.median
- 50.0), kIota
);
41 ASSERT_EQ(data
.average
, 50.5); // avg is acurately calculated.
42 ASSERT_LT(fabs(data
.standard_deviation
- 28.86), kIota
); //sd is ~= 28.86
45 void MergeHistogram(Histogram
& histogram
, Histogram
& other
) {
46 PopulateHistogram(histogram
, 1, 100);
47 PopulateHistogram(other
, 101, 200);
48 histogram
.Merge(other
);
51 histogram
.Data(&data
);
53 ASSERT_LE(fabs(histogram
.Percentile(100.0) - 200.0), kIota
);
54 ASSERT_LE(fabs(data
.percentile99
- 198.0), kIota
);
55 ASSERT_LE(fabs(data
.percentile95
- 190.0), kIota
);
56 ASSERT_LE(fabs(data
.median
- 100.0), kIota
);
57 ASSERT_EQ(data
.average
, 100.5); // avg is acurately calculated.
58 ASSERT_LT(fabs(data
.standard_deviation
- 57.73), kIota
); //sd is ~= 57.73
61 void EmptyHistogram(Histogram
& histogram
) {
62 ASSERT_EQ(histogram
.min(), bucketMapper
.LastValue());
63 ASSERT_EQ(histogram
.max(), 0);
64 ASSERT_EQ(histogram
.num(), 0);
65 ASSERT_EQ(histogram
.Median(), 0.0);
66 ASSERT_EQ(histogram
.Percentile(85.0), 0.0);
67 ASSERT_EQ(histogram
.Average(), 0.0);
68 ASSERT_EQ(histogram
.StandardDeviation(), 0.0);
71 void ClearHistogram(Histogram
& histogram
) {
72 for (uint64_t i
= 1; i
<= 100; i
++) {
76 ASSERT_TRUE(histogram
.Empty());
77 ASSERT_EQ(histogram
.Median(), 0);
78 ASSERT_EQ(histogram
.Percentile(85.0), 0);
79 ASSERT_EQ(histogram
.Average(), 0);
82 TEST_F(HistogramTest
, BasicOperation
) {
83 HistogramImpl histogram
;
84 BasicOperation(histogram
);
86 HistogramWindowingImpl histogramWindowing
;
87 BasicOperation(histogramWindowing
);
90 TEST_F(HistogramTest
, MergeHistogram
) {
91 HistogramImpl histogram
;
93 MergeHistogram(histogram
, other
);
95 HistogramWindowingImpl histogramWindowing
;
96 HistogramWindowingImpl otherWindowing
;
97 MergeHistogram(histogramWindowing
, otherWindowing
);
100 TEST_F(HistogramTest
, EmptyHistogram
) {
101 HistogramImpl histogram
;
102 EmptyHistogram(histogram
);
104 HistogramWindowingImpl histogramWindowing
;
105 EmptyHistogram(histogramWindowing
);
108 TEST_F(HistogramTest
, ClearHistogram
) {
109 HistogramImpl histogram
;
110 ClearHistogram(histogram
);
112 HistogramWindowingImpl histogramWindowing
;
113 ClearHistogram(histogramWindowing
);
116 TEST_F(HistogramTest
, HistogramWindowingExpire
) {
117 uint64_t num_windows
= 3;
118 int micros_per_window
= 1000000;
119 uint64_t min_num_per_window
= 0;
121 HistogramWindowingImpl
122 histogramWindowing(num_windows
, micros_per_window
, min_num_per_window
);
124 PopulateHistogram(histogramWindowing
, 1, 1, 100);
125 env
->SleepForMicroseconds(micros_per_window
);
126 ASSERT_EQ(histogramWindowing
.num(), 100);
127 ASSERT_EQ(histogramWindowing
.min(), 1);
128 ASSERT_EQ(histogramWindowing
.max(), 1);
129 ASSERT_EQ(histogramWindowing
.Average(), 1);
131 PopulateHistogram(histogramWindowing
, 2, 2, 100);
132 env
->SleepForMicroseconds(micros_per_window
);
133 ASSERT_EQ(histogramWindowing
.num(), 200);
134 ASSERT_EQ(histogramWindowing
.min(), 1);
135 ASSERT_EQ(histogramWindowing
.max(), 2);
136 ASSERT_EQ(histogramWindowing
.Average(), 1.5);
138 PopulateHistogram(histogramWindowing
, 3, 3, 100);
139 env
->SleepForMicroseconds(micros_per_window
);
140 ASSERT_EQ(histogramWindowing
.num(), 300);
141 ASSERT_EQ(histogramWindowing
.min(), 1);
142 ASSERT_EQ(histogramWindowing
.max(), 3);
143 ASSERT_EQ(histogramWindowing
.Average(), 2.0);
145 // dropping oldest window with value 1, remaining 2 ~ 4
146 PopulateHistogram(histogramWindowing
, 4, 4, 100);
147 env
->SleepForMicroseconds(micros_per_window
);
148 ASSERT_EQ(histogramWindowing
.num(), 300);
149 ASSERT_EQ(histogramWindowing
.min(), 2);
150 ASSERT_EQ(histogramWindowing
.max(), 4);
151 ASSERT_EQ(histogramWindowing
.Average(), 3.0);
153 // dropping oldest window with value 2, remaining 3 ~ 5
154 PopulateHistogram(histogramWindowing
, 5, 5, 100);
155 env
->SleepForMicroseconds(micros_per_window
);
156 ASSERT_EQ(histogramWindowing
.num(), 300);
157 ASSERT_EQ(histogramWindowing
.min(), 3);
158 ASSERT_EQ(histogramWindowing
.max(), 5);
159 ASSERT_EQ(histogramWindowing
.Average(), 4.0);
162 TEST_F(HistogramTest
, HistogramWindowingMerge
) {
163 uint64_t num_windows
= 3;
164 int micros_per_window
= 1000000;
165 uint64_t min_num_per_window
= 0;
167 HistogramWindowingImpl
168 histogramWindowing(num_windows
, micros_per_window
, min_num_per_window
);
169 HistogramWindowingImpl
170 otherWindowing(num_windows
, micros_per_window
, min_num_per_window
);
172 PopulateHistogram(histogramWindowing
, 1, 1, 100);
173 PopulateHistogram(otherWindowing
, 1, 1, 100);
174 env
->SleepForMicroseconds(micros_per_window
);
176 PopulateHistogram(histogramWindowing
, 2, 2, 100);
177 PopulateHistogram(otherWindowing
, 2, 2, 100);
178 env
->SleepForMicroseconds(micros_per_window
);
180 PopulateHistogram(histogramWindowing
, 3, 3, 100);
181 PopulateHistogram(otherWindowing
, 3, 3, 100);
182 env
->SleepForMicroseconds(micros_per_window
);
184 histogramWindowing
.Merge(otherWindowing
);
185 ASSERT_EQ(histogramWindowing
.num(), 600);
186 ASSERT_EQ(histogramWindowing
.min(), 1);
187 ASSERT_EQ(histogramWindowing
.max(), 3);
188 ASSERT_EQ(histogramWindowing
.Average(), 2.0);
190 // dropping oldest window with value 1, remaining 2 ~ 4
191 PopulateHistogram(histogramWindowing
, 4, 4, 100);
192 env
->SleepForMicroseconds(micros_per_window
);
193 ASSERT_EQ(histogramWindowing
.num(), 500);
194 ASSERT_EQ(histogramWindowing
.min(), 2);
195 ASSERT_EQ(histogramWindowing
.max(), 4);
197 // dropping oldest window with value 2, remaining 3 ~ 5
198 PopulateHistogram(histogramWindowing
, 5, 5, 100);
199 env
->SleepForMicroseconds(micros_per_window
);
200 ASSERT_EQ(histogramWindowing
.num(), 400);
201 ASSERT_EQ(histogramWindowing
.min(), 3);
202 ASSERT_EQ(histogramWindowing
.max(), 5);
205 } // namespace rocksdb
207 int main(int argc
, char** argv
) {
208 ::testing::InitGoogleTest(&argc
, argv
);
209 return RUN_ALL_TESTS();