22 #include <glog/logging.h> 28 template <
typename T,
typename BucketT>
34 : bucketSize_(bucketSize),
min_(min),
max_(max) {
42 if (numBuckets * bucketSize < max - min) {
47 buckets_.assign(
size_t(numBuckets), defaultBucket);
50 template <
typename T,
typename BucketType>
54 }
else if (value >=
max_) {
62 template <
typename T,
typename BucketType>
63 template <
typename CountFn>
65 CountFn countFromBucket)
const {
67 for (
size_t n = 0; n <
buckets_.size(); ++n) {
68 count += countFromBucket(const_cast<const BucketType&>(
buckets_[n]));
73 template <
typename T,
typename BucketType>
74 template <
typename CountFn>
77 CountFn countFromBucket,
79 double* highPct)
const {
86 std::vector<uint64_t> counts(numBuckets);
88 for (
size_t n = 0; n < numBuckets; ++n) {
90 countFromBucket(const_cast<const BucketType&>(
buckets_[n]));
91 counts[n] = bucketCount;
92 totalCount += bucketCount;
98 if (totalCount == 0) {
114 double prevPct = 0.0;
118 for (idx = 0; idx < numBuckets; ++idx) {
119 if (counts[idx] == 0) {
125 curCount += counts[idx];
126 curPct =
static_cast<double>(curCount) / totalCount;
142 template <
typename T,
typename BucketType>
143 template <
typename CountFn,
typename AvgFn>
146 CountFn countFromBucket,
147 AvgFn avgFromBucket)
const {
153 if (lowPct == 0.0 && highPct == 0.0) {
158 if (lowPct == highPct) {
162 return avgFromBucket(
buckets_[bucketIdx]);
165 CHECK_GE(pct, lowPct);
166 CHECK_LE(pct, highPct);
167 CHECK_LT(lowPct, highPct);
173 if (bucketIdx == 0) {
184 LOG(ERROR) <<
"invalid average value in histogram minimum bucket: " << avg
185 <<
" > " <<
min_ <<
": possible integer overflow?";
191 low = high - (2 * (high - avg));
196 }
else if (bucketIdx ==
buckets_.size() - 1) {
200 LOG(ERROR) <<
"invalid average value in histogram maximum bucket: " << avg
201 <<
" < " <<
max_ <<
": possible integer overflow?";
207 high = low + (2 * (avg - low));
215 if (avg < low || avg > high) {
219 LOG(ERROR) <<
"invalid average value in histogram bucket: " << avg
220 <<
" not in range [" << low <<
", " << high
221 <<
"]: possible integer overflow?";
222 return (low + high) / 2;
232 double medianPct = (lowPct + highPct) / 2.0;
233 if (pct < medianPct) {
236 double pctThroughSection = (pct - lowPct) / (medianPct - lowPct);
237 return T(low + ((avg - low) * pctThroughSection));
241 double pctThroughSection = (pct - medianPct) / (highPct - medianPct);
242 return T(avg + ((high - avg) * pctThroughSection));
248 template <
typename T>
261 for (
size_t i = 0;
i <
buckets_.getNumBuckets(); ++
i) {
274 template <
typename T>
276 for (
size_t i = 0;
i <
buckets_.getNumBuckets(); ++
i) {
278 if (skipEmptyBuckets && getBucketByIndex(
i).count == 0) {
281 const auto& bucket = getBucketByIndex(
i);
283 <<
'\t' << bucket.sum <<
'\n';
ValueType getPercentileEstimate(double pct, CountFn countFromBucket, AvgFn avgFromBucket) const
ValueType getBucketMax(size_t idx) const
void toTSV(std::ostream &out, bool skipEmptyBuckets=true) const
size_t getBucketIdx(ValueType value) const
—— Concurrent Priority Queue Implementation ——
uint64_t computeTotalCount(CountFn countFromBucket) const
ValueType getBucketMin(size_t idx) const
std::string debugString() const
std::vector< BucketType > buckets_
void toAppend(char value, Tgt *result)
size_t getPercentileBucketIdx(double pct, CountFn countFromBucket, double *lowPct=nullptr, double *highPct=nullptr) const
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
HistogramBuckets(ValueType bucketSize, ValueType min, ValueType max, const BucketType &defaultBucket)