1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 &smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2017 OVH
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public
10 * License version 2, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include "common/perf_histogram.h"
17 #include "gtest/gtest.h"
20 class PerfHistogramAccessor : public PerfHistogram<DIM> {
22 typedef PerfHistogram<DIM> Base;
24 using Base::PerfHistogram;
26 static int64_t get_bucket_for_axis(
27 int64_t value, const PerfHistogramCommon::axis_config_d& axis_config) {
28 return Base::get_bucket_for_axis(value, axis_config);
31 static std::vector<std::pair<int64_t, int64_t>> get_axis_bucket_ranges(
32 const PerfHistogramCommon::axis_config_d& axis_config) {
33 return Base::get_axis_bucket_ranges(axis_config);
36 const typename Base::axis_config_d& get_axis_config(int num) {
37 return Base::m_axes_config[num];
40 template <typename F1, typename F2, typename F3>
41 void visit_values(F1 f1, F2 f2, F3 f3) {
42 Base::visit_values(f1, f2, f3);
46 TEST(PerfHistogram, GetBucketForAxis) {
47 PerfHistogramCommon::axis_config_d linear{
48 "", PerfHistogramCommon::SCALE_LINEAR, 100, 3, 4};
50 ASSERT_EQ(0, PerfHistogramAccessor<1>::get_bucket_for_axis(-1, linear));
51 ASSERT_EQ(0, PerfHistogramAccessor<1>::get_bucket_for_axis(0, linear));
52 ASSERT_EQ(0, PerfHistogramAccessor<1>::get_bucket_for_axis(99, linear));
53 ASSERT_EQ(1, PerfHistogramAccessor<1>::get_bucket_for_axis(100, linear));
54 ASSERT_EQ(1, PerfHistogramAccessor<1>::get_bucket_for_axis(101, linear));
55 ASSERT_EQ(1, PerfHistogramAccessor<1>::get_bucket_for_axis(102, linear));
56 ASSERT_EQ(2, PerfHistogramAccessor<1>::get_bucket_for_axis(103, linear));
57 ASSERT_EQ(2, PerfHistogramAccessor<1>::get_bucket_for_axis(105, linear));
58 ASSERT_EQ(3, PerfHistogramAccessor<1>::get_bucket_for_axis(106, linear));
59 ASSERT_EQ(3, PerfHistogramAccessor<1>::get_bucket_for_axis(108, linear));
60 ASSERT_EQ(3, PerfHistogramAccessor<1>::get_bucket_for_axis(109, linear));
62 ASSERT_EQ(0, PerfHistogramAccessor<1>::get_bucket_for_axis(
63 std::numeric_limits<int64_t>::min(), linear));
64 ASSERT_EQ(3, PerfHistogramAccessor<1>::get_bucket_for_axis(
65 std::numeric_limits<int64_t>::max(), linear));
67 PerfHistogramCommon::axis_config_d logarithmic{
68 "", PerfHistogramCommon::SCALE_LOG2, 100, 3, 5};
70 ASSERT_EQ(0, PerfHistogramAccessor<1>::get_bucket_for_axis(-1, logarithmic));
71 ASSERT_EQ(0, PerfHistogramAccessor<1>::get_bucket_for_axis(0, logarithmic));
72 ASSERT_EQ(0, PerfHistogramAccessor<1>::get_bucket_for_axis(99, logarithmic));
73 ASSERT_EQ(1, PerfHistogramAccessor<1>::get_bucket_for_axis(100, logarithmic));
74 ASSERT_EQ(1, PerfHistogramAccessor<1>::get_bucket_for_axis(101, logarithmic));
75 ASSERT_EQ(1, PerfHistogramAccessor<1>::get_bucket_for_axis(102, logarithmic));
76 ASSERT_EQ(2, PerfHistogramAccessor<1>::get_bucket_for_axis(103, logarithmic));
77 ASSERT_EQ(2, PerfHistogramAccessor<1>::get_bucket_for_axis(105, logarithmic));
78 ASSERT_EQ(3, PerfHistogramAccessor<1>::get_bucket_for_axis(106, logarithmic));
79 ASSERT_EQ(3, PerfHistogramAccessor<1>::get_bucket_for_axis(111, logarithmic));
80 ASSERT_EQ(4, PerfHistogramAccessor<1>::get_bucket_for_axis(112, logarithmic));
81 ASSERT_EQ(4, PerfHistogramAccessor<1>::get_bucket_for_axis(124, logarithmic));
83 ASSERT_EQ(0, PerfHistogramAccessor<1>::get_bucket_for_axis(
84 std::numeric_limits<int64_t>::min(), logarithmic));
85 ASSERT_EQ(4, PerfHistogramAccessor<1>::get_bucket_for_axis(
86 std::numeric_limits<int64_t>::max(), logarithmic));
89 static const int XS = 5;
90 static const int YS = 7;
92 static const auto x_axis = PerfHistogramCommon::axis_config_d{
93 "x", PerfHistogramCommon::SCALE_LINEAR, 0, 1, XS};
94 static const auto y_axis = PerfHistogramCommon::axis_config_d{
95 "y", PerfHistogramCommon::SCALE_LOG2, 0, 1, YS};
97 TEST(PerfHistogram, ZeroedInitially) {
98 PerfHistogramAccessor<2> h{x_axis, y_axis};
99 for (int x = 0; x < XS; ++x) {
100 for (int y = 0; y < YS; ++y) {
101 ASSERT_EQ(0UL, h.read_bucket(x, y));
106 TEST(PerfHistogram, Copy) {
107 PerfHistogramAccessor<2> h1{x_axis, y_axis};
112 PerfHistogramAccessor<2> h2 = h1;
117 h1.inc_bucket(cx, cy);
119 // Axes configuration must be equal
120 for (int i = 0; i < 2; i++) {
121 const auto& ac1 = h1.get_axis_config(i);
122 const auto& ac2 = h2.get_axis_config(i);
123 ASSERT_EQ(ac1.m_name, ac2.m_name);
124 ASSERT_EQ(ac1.m_scale_type, ac2.m_scale_type);
125 ASSERT_EQ(ac1.m_min, ac2.m_min);
126 ASSERT_EQ(ac1.m_quant_size, ac2.m_quant_size);
127 ASSERT_EQ(ac1.m_buckets, ac2.m_buckets);
130 // second histogram must have histogram values equal to the first
131 // one at the time of copy
132 for (int x = 0; x < XS; x++) {
133 for (int y = 0; y < YS; y++) {
134 if (x == cx && y == cy) {
135 ASSERT_NE(h1.read_bucket(x, y), h2.read_bucket(x, y));
137 ASSERT_EQ(h1.read_bucket(x, y), h2.read_bucket(x, y));
143 TEST(PerfHistogram, SimpleValues) {
144 PerfHistogramAccessor<2> h{x_axis, y_axis};
145 ASSERT_EQ(0UL, h.read_bucket(1, 1));
147 ASSERT_EQ(1UL, h.read_bucket(1, 1));
149 ASSERT_EQ(0UL, h.read_bucket(2, 2));
151 ASSERT_EQ(1UL, h.read_bucket(2, 2));
153 ASSERT_EQ(0UL, h.read_bucket(3, 3));
155 ASSERT_EQ(1UL, h.read_bucket(3, 3));
157 ASSERT_EQ(0UL, h.read_bucket(4, 3));
159 ASSERT_EQ(1UL, h.read_bucket(4, 3));
162 TEST(PerfHistogram, OneBucketRange) {
163 auto ranges = PerfHistogramAccessor<1>::get_axis_bucket_ranges(
164 PerfHistogramCommon::axis_config_d{"", PerfHistogramCommon::SCALE_LINEAR,
167 ASSERT_EQ(1UL, ranges.size());
168 ASSERT_EQ(std::numeric_limits<int64_t>::min(), ranges[0].first);
169 ASSERT_EQ(std::numeric_limits<int64_t>::max(), ranges[0].second);
172 TEST(PerfHistogram, TwoBucketRange) {
173 auto ranges = PerfHistogramAccessor<1>::get_axis_bucket_ranges(
174 PerfHistogramCommon::axis_config_d{"", PerfHistogramCommon::SCALE_LINEAR,
177 ASSERT_EQ(2UL, ranges.size());
178 ASSERT_EQ(std::numeric_limits<int64_t>::min(), ranges[0].first);
179 ASSERT_EQ(-1, ranges[0].second);
180 ASSERT_EQ(0, ranges[1].first);
181 ASSERT_EQ(std::numeric_limits<int64_t>::max(), ranges[1].second);
184 TEST(PerfHistogram, LinearBucketRange) {
185 PerfHistogramCommon::axis_config_d ac{"", PerfHistogramCommon::SCALE_LINEAR,
187 auto ranges = PerfHistogramAccessor<1>::get_axis_bucket_ranges(ac);
189 for (size_t i = 0; i < ranges.size(); ++i) {
191 static_cast<long>(i), PerfHistogramAccessor<1>::get_bucket_for_axis(ranges[i].first, ac));
193 static_cast<long>(i), PerfHistogramAccessor<1>::get_bucket_for_axis(ranges[i].second, ac));
196 for (size_t i = 1; i < ranges.size(); ++i) {
197 ASSERT_EQ(ranges[i].first, ranges[i - 1].second + 1);
201 TEST(PerfHistogram, LogarithmicBucketRange) {
202 PerfHistogramCommon::axis_config_d ac{"", PerfHistogramCommon::SCALE_LOG2,
204 auto ranges = PerfHistogramAccessor<1>::get_axis_bucket_ranges(ac);
206 for (size_t i = 0; i < ranges.size(); ++i) {
208 static_cast<long>(i), PerfHistogramAccessor<1>::get_bucket_for_axis(ranges[i].first, ac));
210 static_cast<long>(i), PerfHistogramAccessor<1>::get_bucket_for_axis(ranges[i].second, ac));
213 for (size_t i = 1; i < ranges.size(); ++i) {
214 ASSERT_EQ(ranges[i].first, ranges[i - 1].second + 1);
218 TEST(PerfHistogram, AxisAddressing) {
219 PerfHistogramCommon::axis_config_d ac1{"", PerfHistogramCommon::SCALE_LINEAR,
221 PerfHistogramCommon::axis_config_d ac2{"", PerfHistogramCommon::SCALE_LINEAR,
223 PerfHistogramCommon::axis_config_d ac3{"", PerfHistogramCommon::SCALE_LINEAR,
226 PerfHistogramAccessor<3> h{ac1, ac2, ac3};
228 h.inc(1, 2, 3); // Should end up in buckets 2, 3, 4
229 h.inc_bucket(4, 5, 6);
231 std::vector<int64_t> rawValues;
232 h.visit_values([](int) {},
233 [&rawValues](int64_t value) { rawValues.push_back(value); },
236 for (size_t i = 0; i < rawValues.size(); ++i) {
238 case 4 + 11 * (3 + 9 * 2):
239 case 6 + 11 * (5 + 9 * 4):
240 ASSERT_EQ(1, rawValues[i]);
243 ASSERT_EQ(0, rawValues[i]);