Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions include/tscpp/util/Histogram.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

#pragma once

#include <stdint.h>
#include <cstdint>
#include <array>

namespace ts
Expand Down Expand Up @@ -65,17 +65,17 @@ template <auto R, auto S> class Histogram
/// Number of bits to split each base range in to span buckets.
static constexpr raw_type N_SPAN_BITS = S;
/// Number of buckets per span.
static constexpr raw_type N_SPAN_BUCKETS = 1 << N_SPAN_BITS;
static constexpr raw_type N_SPAN_BUCKETS = raw_type(1) << N_SPAN_BITS;
/// Mask to extract the local bucket index from a sample.
static constexpr raw_type SPAN_MASK = (1 << N_SPAN_BITS) - 1;
static constexpr raw_type SPAN_MASK = (raw_type(1) << N_SPAN_BITS) - 1;
/// Initial mask to find the MSB in the sample.
static constexpr raw_type MSB_MASK = 1 << (N_RANGE_BITS + N_SPAN_BITS - 1);
/// Total number of buckets - 1 for overflow and an extra range for less than @c LOWER_BOUND
static constexpr raw_type MSB_MASK = raw_type(1) << (N_RANGE_BITS + N_SPAN_BITS - 1);
/// Total number of buckets - 1 for overflow and an extra range for less than @c UNDERFLOW_BOUND
static constexpr raw_type N_BUCKETS = ((N_RANGE_BITS + 1) * N_SPAN_BUCKETS) + 1;
/// Samples less than this go in the underflow range.
static constexpr raw_type LOWER_BOUND = 1 << N_SPAN_BITS;
static constexpr raw_type UNDERFLOW_BOUND = raw_type(1) << N_SPAN_BITS;
/// Sample equal or greater than this go in the overflow bucket.
static constexpr raw_type UPPER_BOUND = 1 << (N_RANGE_BITS + N_SPAN_BITS + 1);
static constexpr raw_type OVERFLOW_BOUND = raw_type(1) << (N_RANGE_BITS + N_SPAN_BITS + 1);

/** Add @sample to the histogram.
*
Expand All @@ -97,12 +97,12 @@ template <auto R, auto S> class Histogram
*/
raw_type operator[](unsigned idx);

/** Lower bound for samples in bucket.
/** Minimum value for samples in bucket.
*
* @param idx Index of the bucket.
* @return The smallest sample value that will increment the bucket.
*/
static raw_type lower_bound(unsigned idx);
static raw_type min_for_bucket(unsigned idx);

/** Add counts from another histogram.
*
Expand Down Expand Up @@ -143,15 +143,15 @@ auto
Histogram<R, S>::operator()(raw_type sample) -> self_type &
{
int idx = N_BUCKETS - 1; // index of overflow bucket
if (sample < LOWER_BOUND) {
idx = sample; // sample -> bucket is identity in the underflow range.
} else if (sample < UPPER_BOUND) { // not overflow bucket.
idx -= N_SPAN_BUCKETS; // bottom bucket in the range.
auto mask = MSB_MASK; // Mask to probe for bit set.
if (sample < UNDERFLOW_BOUND) {
idx = sample; // sample -> bucket is identity in the underflow range.
} else if (sample < OVERFLOW_BOUND) { // not overflow bucket.
idx -= N_SPAN_BUCKETS; // bottom bucket in the range.
auto mask = MSB_MASK; // Mask to probe for bit set.
// Shift needed after finding the MSB to put the span bits in the LSBs.
unsigned normalize_shift_count = N_RANGE_BITS - 1;
// Walk the mask bit down until the MSB is found. Each span bumps down the bucket index
// and the shift for the span bits. An MSB will be found because @a sample >= @c LOWER_BOUND
// and the shift for the span bits. An MSB will be found because @a sample >= @c UNDERFLOW_BOUND
// The MSB is not before @c MSB_MASK because @a sample < @c UPPER_BOUND
while (0 == (sample & mask)) {
mask >>= 1;
Expand All @@ -166,7 +166,7 @@ Histogram<R, S>::operator()(raw_type sample) -> self_type &

template <auto R, auto S>
auto
Histogram<R, S>::lower_bound(unsigned idx) -> raw_type
Histogram<R, S>::min_for_bucket(unsigned idx) -> raw_type
{
auto range = idx / N_SPAN_BUCKETS;
raw_type base = 0; // minimum value for the range (not span!).
Expand Down
4 changes: 2 additions & 2 deletions iocore/eventsystem/UnixEventProcessor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -523,14 +523,14 @@ EventProcessor::start(int n_event_threads, size_t stacksize)
// Event loop timings.
for (Graph::raw_type id = 0; id < Graph::N_BUCKETS; ++id) {
snprintf(name, sizeof(name), "%s%zums", EThread::Metrics::LOOP_HISTOGRAM_STAT_STEM.data(),
static_cast<size_t>(EThread::Metrics::LOOP_HISTOGRAM_BUCKET_SIZE.count() * Graph::lower_bound(id)));
static_cast<size_t>(EThread::Metrics::LOOP_HISTOGRAM_BUCKET_SIZE.count() * Graph::min_for_bucket(id)));
RecRegisterRawStat(rsb, RECT_PROCESS, name, RECD_INT, RECP_NON_PERSISTENT, stat_idx++, NULL);
}

// plugin API timings
for (Graph::raw_type id = 0; id < Graph::N_BUCKETS; ++id) {
snprintf(name, sizeof(name), "%s%zums", EThread::Metrics::API_HISTOGRAM_STAT_STEM.data(),
static_cast<size_t>(EThread::Metrics::API_HISTOGRAM_BUCKET_SIZE.count() * Graph::lower_bound(id)));
static_cast<size_t>(EThread::Metrics::API_HISTOGRAM_BUCKET_SIZE.count() * Graph::min_for_bucket(id)));
RecRegisterRawStat(rsb, RECT_PROCESS, name, RECD_INT, RECP_NON_PERSISTENT, stat_idx++, NULL);
}

Expand Down
20 changes: 10 additions & 10 deletions src/tscore/unit_tests/test_Histogram.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,22 @@ TEST_CASE("Histogram Basic", "[libts][histogram]")
h(12);
REQUIRE(h[10] == 1);

REQUIRE(h.lower_bound(0) == 0);
REQUIRE(h.lower_bound(3) == 3);
REQUIRE(h.lower_bound(4) == 4);
REQUIRE(h.lower_bound(8) == 8);
REQUIRE(h.lower_bound(9) == 10);
REQUIRE(h.lower_bound(12) == 16);
REQUIRE(h.lower_bound(13) == 20);
REQUIRE(h.lower_bound(16) == 32);
REQUIRE(h.lower_bound(17) == 40);
REQUIRE(h.min_for_bucket(0) == 0);
REQUIRE(h.min_for_bucket(3) == 3);
REQUIRE(h.min_for_bucket(4) == 4);
REQUIRE(h.min_for_bucket(8) == 8);
REQUIRE(h.min_for_bucket(9) == 10);
REQUIRE(h.min_for_bucket(12) == 16);
REQUIRE(h.min_for_bucket(13) == 20);
REQUIRE(h.min_for_bucket(16) == 32);
REQUIRE(h.min_for_bucket(17) == 40);

for (auto x : {0, 1, 4, 6, 19, 27, 36, 409, 16000, 1097}) {
h(x);
}
REQUIRE(h[0] == 1);
REQUIRE(h[1] == 1);
REQUIRE(h[2] == 0);
REQUIRE(h[12] == 1); // sample 19 shoud be here.
REQUIRE(h[12] == 1); // sample 19 should be here.
REQUIRE(h[14] == 1); // sample 27 should be here.
};