/*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <vector>
#include <stdexcept>
-#include "folly/detail/Stats.h"
+#include <folly/detail/Stats.h>
namespace folly {
return min_ + (idx * bucketSize_);
}
+ /**
+ * Computes the total number of values stored across all buckets.
+ *
+ * Runs in O(numBuckets)
+ *
+ * @param countFn A function that takes a const BucketType&, and returns the
+ * number of values in that bucket
+ * @return Returns the total number of values stored across all buckets
+ */
+ template <typename CountFn>
+ const uint64_t computeTotalCount(CountFn countFromBucket) const;
+
/**
* Determine which bucket the specified percentile falls into.
*
template <typename CountFn>
unsigned int getPercentileBucketIdx(double pct,
CountFn countFromBucket,
- double* lowPct = NULL,
- double* highPct = NULL) const;
+ double* lowPct = nullptr,
+ double* highPct = nullptr) const;
/**
* Estimate the value at the specified percentile.
}
private:
- const ValueType bucketSize_;
- const ValueType min_;
- const ValueType max_;
+ ValueType bucketSize_;
+ ValueType min_;
+ ValueType max_;
std::vector<BucketType> buckets_;
};
bucket.count += 1;
}
+ /* Add multiple same data points to the histogram */
+ void addRepeatedValue(ValueType value, uint64_t nSamples) {
+ Bucket& bucket = buckets_.getByValue(value);
+ // TODO: It would be nice to handle overflow here.
+ bucket.sum += value * nSamples;
+ bucket.count += nSamples;
+ }
+
/*
* Remove a data point to the histogram
*
void removeValue(ValueType value) {
Bucket& bucket = buckets_.getByValue(value);
// TODO: It would be nice to handle overflow here.
- bucket.sum -= value;
- bucket.count -= 1;
+ if (bucket.count > 0) {
+ bucket.sum -= value;
+ bucket.count -= 1;
+ } else {
+ bucket.sum = ValueType();
+ bucket.count = 0;
+ }
+ }
+
+ /* Remove multiple same data points from the histogram */
+ void removeRepeatedValue(ValueType value, uint64_t nSamples) {
+ Bucket& bucket = buckets_.getByValue(value);
+ // TODO: It would be nice to handle overflow here.
+ if (bucket.count >= nSamples) {
+ bucket.sum -= value * nSamples;
+ bucket.count -= nSamples;
+ } else {
+ bucket.sum = ValueType();
+ bucket.count = 0;
+ }
}
/* Remove all data points from the histogram */
void clear() {
- for (int i = 0; i < buckets_.getNumBuckets(); i++) {
+ for (unsigned int i = 0; i < buckets_.getNumBuckets(); i++) {
buckets_.getByIndex(i).clear();
}
}
+ /* Subtract another histogram data from the histogram */
+ void subtract(const Histogram &hist) {
+ // the two histogram bucket definitions must match to support
+ // subtract.
+ if (getBucketSize() != hist.getBucketSize() ||
+ getMin() != hist.getMin() ||
+ getMax() != hist.getMax() ||
+ getNumBuckets() != hist.getNumBuckets() ) {
+ throw std::invalid_argument("Cannot subtract input histogram.");
+ }
+
+ for (unsigned int i = 0; i < buckets_.getNumBuckets(); i++) {
+ buckets_.getByIndex(i) -= hist.buckets_.getByIndex(i);
+ }
+ }
+
/* Merge two histogram data together */
- void merge(Histogram &hist) {
+ void merge(const Histogram &hist) {
// the two histogram bucket definitions must match to support
// a merge.
if (getBucketSize() != hist.getBucketSize() ||
throw std::invalid_argument("Cannot merge from input histogram.");
}
- for (int i = 0; i < buckets_.getNumBuckets(); i++) {
+ for (unsigned int i = 0; i < buckets_.getNumBuckets(); i++) {
buckets_.getByIndex(i) += hist.buckets_.getByIndex(i);
}
}
/* Copy bucket values from another histogram */
- void copy(Histogram &hist) {
+ void copy(const Histogram &hist) {
// the two histogram bucket definition must match
if (getBucketSize() != hist.getBucketSize() ||
getMin() != hist.getMin() ||
throw std::invalid_argument("Cannot copy from input histogram.");
}
- for (int i = 0; i < buckets_.getNumBuckets(); i++) {
+ for (unsigned int i = 0; i < buckets_.getNumBuckets(); i++) {
buckets_.getByIndex(i) = hist.buckets_.getByIndex(i);
}
}
return buckets_.getBucketMax(idx);
}
+ /**
+ * Computes the total number of values stored across all buckets.
+ *
+ * Runs in O(numBuckets)
+ */
+ const uint64_t computeTotalCount() const {
+ CountFromBucket countFn;
+ return buckets_.computeTotalCount(countFn);
+ }
+
/*
* Get the bucket that the specified percentile falls into
*
* returned in the lowPct and highPct arguments, if they are non-NULL.
*/
unsigned int getPercentileBucketIdx(double pct,
- double* lowPct = NULL,
- double* highPct = NULL) const {
+ double* lowPct = nullptr,
+ double* highPct = nullptr) const {
// We unfortunately can't use lambdas here yet;
// Some users of this code are still built with gcc-4.4.
CountFromBucket countFn;
*/
void toTSV(std::ostream& out, bool skipEmptyBuckets = true) const;
- private:
struct CountFromBucket {
uint64_t operator()(const Bucket& bucket) const {
return bucket.count;
}
};
+ private:
detail::HistogramBuckets<ValueType, Bucket> buckets_;
};