Skip to content

Commit 8330f81

Browse files
rdemellowdaverigby
authored andcommitted
MB-41510: Tidy HdrHistogram class
Tidy up HdrHistogram class by adding const and static keywords where applicable and use fmt over std::stringstream. Also ensure we don't perform self assignment in HdrHistogram's assignment operator. Change-Id: I5498f3d2bf08afe7cb7269906b9f13076c5e2ab4 Reviewed-on: http://review.couchbase.org/c/kv_engine/+/136612 Tested-by: Build Bot <[email protected]> Reviewed-by: Dave Rigby <[email protected]>
1 parent 1cd1265 commit 8330f81

File tree

4 files changed

+116
-117
lines changed

4 files changed

+116
-117
lines changed

engines/ep/tests/module_tests/hdrhistogram_test.cc

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ TEST(HdrHistogramTest, linearIteratorTest) {
8080
HdrHistogram::Iterator iter{
8181
histogram.makeLinearIterator(/* valueUnitsPerBucket */ 1)};
8282
uint64_t valueCount = 0;
83-
while (auto result = histogram.getNextValueAndCount(iter)) {
83+
while (auto result = iter.getNextValueAndCount()) {
8484
EXPECT_EQ(valueCount, result->first);
8585
++valueCount;
8686
}
@@ -104,7 +104,7 @@ TEST(HdrHistogramTest, logIteratorBaseTwoTest) {
104104

105105
uint64_t countSum = 0;
106106
uint64_t bucketIndex = 0;
107-
while (auto result = histogram.getNextValueAndCount(iter)) {
107+
while (auto result = iter.getNextValueAndCount()) {
108108
// Check that the values of the buckets increase exponentially
109109
EXPECT_EQ(pow(iteratorBase, bucketIndex) - 1, result->first);
110110
// Check that the width of the bucket is the same number as the count
@@ -138,7 +138,7 @@ TEST(HdrHistogramTest, logIteratorBaseFiveTest) {
138138

139139
uint64_t countSum = 0;
140140
uint64_t bucketIndex = 0;
141-
while (auto result = histogram.getNextValueAndCount(iter)) {
141+
while (auto result = iter.getNextValueAndCount()) {
142142
// Check that the values of the buckets increase exponentially
143143
EXPECT_EQ(pow(iteratorBase, bucketIndex) - 1, result->first);
144144
// Check that the width of the bucket is the same number as the count
@@ -161,7 +161,7 @@ TEST(HdrHistogramTest, addValueAndCountTest) {
161161
histogram.addValueAndCount(0, 100);
162162
// Need to create the iterator after we have added the data
163163
HdrHistogram::Iterator iter{histogram.makeLinearIterator(1)};
164-
while (auto result = histogram.getNextValueAndCount(iter)) {
164+
while (auto result = iter.getNextValueAndCount()) {
165165
EXPECT_EQ(0, result->first);
166166
EXPECT_EQ(100, result->second);
167167
}
@@ -288,7 +288,7 @@ TEST(HdrHistogramTest, addValueParallel) {
288288
histogram.makeLinearIterator(/* valueUnitsPerBucket */ 1)};
289289
uint64_t valueCount = 0;
290290
// Assert that the right number of values were added to the histogram
291-
while (auto result = histogram.getNextValueAndCount(iter)) {
291+
while (auto result = iter.getNextValueAndCount()) {
292292
ASSERT_EQ(valueCount, result->first);
293293
ASSERT_EQ(threads.size() * numOfAddIterations, result->second);
294294
++valueCount;
@@ -322,8 +322,8 @@ TEST(HdrHistogramTest, aggregationTest) {
322322
histogramTwo.makeLinearIterator(/* valueUnitsPerBucket */ 1)};
323323
uint64_t valueCount = 0;
324324
for (int i = 0; i < 15; i++) {
325-
auto resultOne = histogramOne.getNextValueAndCount(iterOne);
326-
auto resultTwo = histogramOne.getNextValueAndCount(iterTwo);
325+
auto resultOne = iterOne.getNextValueAndCount();
326+
auto resultTwo = iterTwo.getNextValueAndCount();
327327
// check values are the same for both histograms
328328
EXPECT_EQ(valueCount, resultTwo->first);
329329
EXPECT_EQ(valueCount, resultOne->first);
@@ -357,8 +357,8 @@ TEST(HdrHistogramTest, aggregationTestEmptyLhr) {
357357
// Max value of LHS should be updated too 200 thus counts should be the
358358
// same for every value in both histograms
359359
for (int i = 0; i < 200; i++) {
360-
auto resultOne = histogramOne.getNextValueAndCount(iterOne);
361-
auto resultTwo = histogramOne.getNextValueAndCount(iterTwo);
360+
auto resultOne = iterOne.getNextValueAndCount();
361+
auto resultTwo = iterTwo.getNextValueAndCount();
362362
// check values are the same for both histograms
363363
EXPECT_EQ(resultOne->first, resultTwo->first);
364364
// check that the counts for each value are the same
@@ -386,7 +386,7 @@ TEST(HdrHistogramTest, aggregationTestEmptyRhs) {
386386

387387
uint64_t valueCount = 0;
388388
// make sure the histogram has expanded in size for all 200 values
389-
while (auto result = histogramOne.getNextValueAndCount(iter)) {
389+
while (auto result = iter.getNextValueAndCount()) {
390390
EXPECT_EQ(valueCount, result->first);
391391
EXPECT_EQ(1, result->second);
392392
++valueCount;
@@ -413,7 +413,7 @@ TEST(HdrHistogramTest, int32MaxSizeTest) {
413413
EXPECT_EQ(0, histogram.getMinValue());
414414

415415
HdrHistogram::Iterator iter{histogram.getHistogramsIterator()};
416-
auto res = histogram.getNextBucketLowHighAndCount(iter);
416+
auto res = iter.getNextBucketLowHighAndCount();
417417
EXPECT_TRUE(res);
418418
// The 3rd field [2] of the returned tuple is the count
419419
EXPECT_EQ(limit, std::get<2>(*res));
@@ -429,7 +429,7 @@ TEST(HdrHistogramTest, int32MaxSizeTest) {
429429
EXPECT_EQ(0, histogram.getMinValue());
430430

431431
HdrHistogram::Iterator iter2{histogram.getHistogramsIterator()};
432-
auto res2 = histogram.getNextBucketLowHighAndCount(iter2);
432+
auto res2 = iter2.getNextBucketLowHighAndCount();
433433
EXPECT_TRUE(res2);
434434
// The 3rd field [2] of the returned tuple is the count
435435
EXPECT_EQ(limit, std::get<2>(*res2));
@@ -457,7 +457,7 @@ TEST(HdrHistogramTest, int64MaxSizeTest) {
457457
EXPECT_EQ(0, histogram.getMinValue());
458458

459459
HdrHistogram::Iterator iter{histogram.getHistogramsIterator()};
460-
auto res = histogram.getNextBucketLowHighAndCount(iter);
460+
auto res = iter.getNextBucketLowHighAndCount();
461461
EXPECT_TRUE(res);
462462
// The 3rd field [2] of the returned tuple is the count
463463
EXPECT_EQ(limit, std::get<2>(*res));
@@ -469,7 +469,7 @@ TEST(HdrHistogramTest, int64MaxSizeTest) {
469469
static std::vector<std::optional<std::pair<uint64_t, double>>> getAllValues(
470470
const HdrHistogram& histo, HdrHistogram::Iterator& iter) {
471471
std::vector<std::optional<std::pair<uint64_t, double>>> values;
472-
while (auto pair = histo.getNextValueAndPercentile(iter)) {
472+
while (auto pair = iter.getNextValueAndPercentile()) {
473473
if (!pair.has_value())
474474
break;
475475
values.push_back(pair);

statistics/collector.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ void StatCollector::addStat(const cb::stats::StatDef& k,
4343
histData.sampleCount = v.getValueCount();
4444

4545
HdrHistogram::Iterator iter{v.getHistogramsIterator()};
46-
while (auto result = v.getNextBucketLowHighAndCount(iter)) {
46+
while (auto result = iter.getNextBucketLowHighAndCount()) {
4747
auto [lower, upper, count] = *result;
4848

4949
histData.buckets.push_back({lower, upper, count});

utilities/hdrhistogram.cc

Lines changed: 56 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
#include <folly/lang/Assume.h>
2121
#include <nlohmann/json.hpp>
2222
#include <platform/cb_malloc.h>
23+
#include <spdlog/fmt/fmt.h>
2324
#include <iostream>
2425
#include <optional>
25-
#include <sstream>
2626

2727
// Custom deleter for the hdr_histogram struct.
2828
void HdrHistogram::HdrDeleter::operator()(struct hdr_histogram* val) {
@@ -85,6 +85,17 @@ HdrHistogram& HdrHistogram::operator+=(const HdrHistogram& other) {
8585
return *this;
8686
}
8787

88+
HdrHistogram& HdrHistogram::operator=(const HdrHistogram& other) {
89+
if (this != &other) {
90+
// reset this object to make sure we are in a state to copy too
91+
this->reset();
92+
// take advantage of the code already written in for the addition
93+
// assigment operator
94+
*this += other;
95+
}
96+
return *this;
97+
}
98+
8899
bool HdrHistogram::addValue(uint64_t v) {
89100
// A hdr_histogram cannot store 0, therefore we add a bias of +1.
90101
int64_t vBiased = v + 1;
@@ -187,26 +198,26 @@ HdrHistogram::Iterator HdrHistogram::getHistogramsIterator() const {
187198
return makeIterator(defaultIterationMode);
188199
}
189200

190-
std::optional<std::pair<uint64_t, uint64_t>> HdrHistogram::getNextValueAndCount(
191-
Iterator& iter) const {
201+
std::optional<std::pair<uint64_t, uint64_t>>
202+
HdrHistogram::Iterator::getNextValueAndCount() {
192203
std::optional<std::pair<uint64_t, uint64_t>> valueAndCount;
193-
if (hdr_iter_next(&iter)) {
194-
auto value = static_cast<uint64_t>(iter.value);
204+
if (hdr_iter_next(this)) {
205+
auto value = static_cast<uint64_t>(this->value);
195206
uint64_t count = 0;
196-
switch (iter.type) {
207+
switch (type) {
197208
case Iterator::IterMode::Log:
198-
count = iter.specifics.log.count_added_in_this_iteration_step;
209+
count = specifics.log.count_added_in_this_iteration_step;
199210
break;
200211
case Iterator::IterMode::Linear:
201-
count = iter.specifics.linear.count_added_in_this_iteration_step;
212+
count = specifics.linear.count_added_in_this_iteration_step;
202213
break;
203214
case Iterator::IterMode::Percentiles:
204-
value = iter.highest_equivalent_value;
205-
count = iter.cumulative_count - iter.lastCumulativeCount;
206-
iter.lastCumulativeCount = iter.cumulative_count;
215+
value = highest_equivalent_value;
216+
count = cumulative_count - lastCumulativeCount;
217+
lastCumulativeCount = cumulative_count;
207218
break;
208219
case Iterator::IterMode::Recorded:
209-
count = iter.count;
220+
count = this->count;
210221
break;
211222
}
212223

@@ -220,59 +231,61 @@ std::optional<std::pair<uint64_t, uint64_t>> HdrHistogram::getNextValueAndCount(
220231
}
221232

222233
std::optional<std::tuple<uint64_t, uint64_t, uint64_t>>
223-
HdrHistogram::getNextBucketLowHighAndCount(Iterator& iter) const {
234+
HdrHistogram::Iterator::getNextBucketLowHighAndCount() {
224235
std::optional<std::tuple<uint64_t, uint64_t, uint64_t>> bucketHighLowCount;
225-
auto valueAndCount = getNextValueAndCount(iter);
236+
auto valueAndCount = getNextValueAndCount();
226237
if (valueAndCount.has_value()) {
227-
bucketHighLowCount = std::make_tuple(
228-
iter.lastVal, valueAndCount->first, valueAndCount->second);
229-
iter.lastVal = valueAndCount->first;
238+
bucketHighLowCount = {
239+
lastVal, valueAndCount->first, valueAndCount->second};
240+
lastVal = valueAndCount->first;
230241
}
231242
return bucketHighLowCount;
232243
}
233244

234245
std::optional<std::pair<uint64_t, double>>
235-
HdrHistogram::getNextValueAndPercentile(Iterator& iter) const {
246+
HdrHistogram::Iterator::getNextValueAndPercentile() {
236247
std::optional<std::pair<uint64_t, double>> valueAndPer;
237-
if (iter.type == Iterator::IterMode::Percentiles) {
238-
if (hdr_iter_next(&iter)) {
248+
if (type == Iterator::IterMode::Percentiles) {
249+
if (hdr_iter_next(this)) {
239250
// We subtract one from the lowest value as we have added a one
240251
// offset as the underlying hdr_histogram cannot store 0 and
241252
// therefore the value must be greater than or equal to 1.
242-
valueAndPer = std::make_pair(iter.highest_equivalent_value - 1,
243-
iter.specifics.percentiles.percentile);
253+
valueAndPer = {highest_equivalent_value - 1,
254+
specifics.percentiles.percentile};
244255
}
245256
}
246257
return valueAndPer;
247258
}
248259

249-
void HdrHistogram::printPercentiles() const {
250-
hdr_percentiles_print(histogram.rlock()->get(), stdout, 5, 1.0, CLASSIC);
260+
std::string HdrHistogram::Iterator::dumpValues() {
261+
fmt::memory_buffer dump;
262+
while (auto pair = getNextValueAndCount()) {
263+
fmt::format_to(dump,
264+
"Value[{}-{}]\tCount:{}\t\n",
265+
value_iterated_from,
266+
value_iterated_to,
267+
pair->second);
268+
}
269+
fmt::format_to(dump, "Total:\t{}\n", total_count);
270+
return {dump.data(), dump.size()};
251271
}
252272

253-
void HdrHistogram::dumpLinearValues(int64_t bucketWidth) {
254-
auto itr = makeLinearIterator(bucketWidth);
255-
std::cout << dumpValues(itr).str();
273+
void HdrHistogram::printPercentiles() const {
274+
hdr_percentiles_print(histogram.rlock()->get(), stdout, 5, 1.0, CLASSIC);
256275
}
257276

258-
void HdrHistogram::dumpLogValues(int64_t firstBucketWidth, double log_base) {
259-
auto itr = makeLogIterator(firstBucketWidth, log_base);
260-
std::cout << dumpValues(itr).str();
277+
void HdrHistogram::dumpLinearValues(int64_t bucketWidth) const {
278+
HdrHistogram::Iterator itr = makeLinearIterator(bucketWidth);
279+
fmt::print(stdout, itr.dumpValues());
261280
}
262281

263-
std::stringstream HdrHistogram::dumpValues(Iterator& itr) {
264-
std::stringstream dump;
265-
while (auto pair = getNextValueAndCount(itr)) {
266-
dump << "Value[" << itr.value_iterated_from << "-"
267-
<< itr.value_iterated_to << "]\tCount:\t" << pair->second
268-
<< std::endl;
269-
}
270-
dump << "Total:\t" << itr.total_count << std::endl;
271-
272-
return dump;
282+
void HdrHistogram::dumpLogValues(int64_t firstBucketWidth,
283+
double log_base) const {
284+
HdrHistogram::Iterator itr = makeLogIterator(firstBucketWidth, log_base);
285+
fmt::print(stdout, itr.dumpValues());
273286
}
274287

275-
nlohmann::json HdrHistogram::to_json(Iterator::IterMode itrType) {
288+
nlohmann::json HdrHistogram::to_json() const {
276289
nlohmann::json rootObj;
277290

278291
// Five is the number of iteration steps per half-distance to 100%.
@@ -285,7 +298,7 @@ nlohmann::json HdrHistogram::to_json(Iterator::IterMode itrType) {
285298
nlohmann::json dataArr;
286299

287300
int64_t lastval = 0;
288-
while (auto pair = getNextValueAndPercentile(itr)) {
301+
while (auto pair = itr.getNextValueAndPercentile()) {
289302
if (!pair.has_value())
290303
break;
291304

@@ -298,7 +311,7 @@ nlohmann::json HdrHistogram::to_json(Iterator::IterMode itrType) {
298311
return rootObj;
299312
}
300313

301-
std::string HdrHistogram::to_string() {
314+
std::string HdrHistogram::to_string() const {
302315
return to_json().dump();
303316
}
304317

0 commit comments

Comments
 (0)