Make some types and constexprs public
[folly.git] / folly / stats / Histogram.h
index 7a0c0db9d3935463ea51ed2a5ffa210a560d97bf..7b7ee1ed3afcc662e7f1dcb53c97f2759d7722e0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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.
@@ -24,7 +24,7 @@
 #include <vector>
 #include <stdexcept>
 
-#include "folly/detail/Stats.h"
+#include <folly/detail/Stats.h>
 
 namespace folly {
 
@@ -142,6 +142,18 @@ class HistogramBuckets {
     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.
    *
@@ -161,8 +173,8 @@ class HistogramBuckets {
   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.
@@ -202,9 +214,9 @@ class HistogramBuckets {
   }
 
  private:
-  const ValueType bucketSize_;
-  const ValueType min_;
-  const ValueType max_;
+  ValueType bucketSize_;
+  ValueType min_;
+  ValueType max_;
   std::vector<BucketType> buckets_;
 };
 
@@ -238,6 +250,14 @@ class Histogram {
     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
    *
@@ -248,19 +268,53 @@ class 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() ||
@@ -270,13 +324,13 @@ class Histogram {
       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() ||
@@ -285,7 +339,7 @@ class Histogram {
       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);
     }
   }
@@ -334,6 +388,16 @@ class Histogram {
     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
    *
@@ -341,8 +405,8 @@ class Histogram {
    * 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;
@@ -374,7 +438,6 @@ class Histogram {
    */
   void toTSV(std::ostream& out, bool skipEmptyBuckets = true) const;
 
- private:
   struct CountFromBucket {
     uint64_t operator()(const Bucket& bucket) const {
       return bucket.count;
@@ -398,6 +461,7 @@ class Histogram {
     }
   };
 
+ private:
   detail::HistogramBuckets<ValueType, Bucket> buckets_;
 };