Task #906853: Implement ThreadLocalServiceData and reduce lock contentions during...
authorLee Hwa <leehwa@fb.com>
Mon, 6 Aug 2012 20:42:49 +0000 (13:42 -0700)
committerTudor Bosman <tudorb@fb.com>
Sun, 26 Aug 2012 18:13:36 +0000 (11:13 -0700)
Summary:
Cache the counter updates on thread local data structures and aggregate/publish
the data from a separate thread periodically. The ThreadLocalServiceData is
implemented on top of the TLStats data structures.

I am plannig to deploy a private build to production tomorrow to test this
change in production, but figured it might be better to send the diff out first
and get code review feedbacks at the same time.

Test Plan: Run and pass unit tests. Run end-to-end testings on sandbox. (TBD)
Deploy a private build to a production server and make sure the thrift call
latency is reduced.

Reviewed By: xin@fb.com

FB internal diff: D540239

folly/Histogram.h

index 6b7cbcdd2af2d81ac3be18d2e25cd1c959044b1f..f25fcbb0b00d3b186c83b2efacd774e376315c00 100644 (file)
@@ -22,6 +22,7 @@
 #include <limits>
 #include <string>
 #include <vector>
+#include <stdexcept>
 
 namespace folly {
 
@@ -233,6 +234,22 @@ class Histogram {
       count = 0;
     }
 
+    Bucket& merge(const Bucket &bucket) {
+      if (this != &bucket) {
+        sum += bucket.sum;
+        count += bucket.count;
+      }
+      return *this;
+    }
+
+    Bucket& operator=(const Bucket& bucket) {
+      if (this != &bucket) {
+        sum = bucket.sum;
+        count = bucket.count;
+      }
+      return *this;
+    }
+
     ValueType sum;
     uint64_t count;
   };
@@ -269,6 +286,37 @@ class Histogram {
     }
   }
 
+  /* Merge two histogram data together */
+  void merge(Histogram &hist) {
+    // the two histogram bucket definitions must match to support
+    // a merge.
+    if (getBucketSize() != hist.getBucketSize() ||
+        getMin() != hist.getMin() ||
+        getMax() != hist.getMax() ||
+        getNumBuckets() != hist.getNumBuckets() ) {
+      throw std::invalid_argument("Cannot merge from input histogram.");
+    }
+
+    for (int i = 0; i < buckets_.getNumBuckets(); i++) {
+      buckets_.getByIndex(i).merge(hist.buckets_.getByIndex(i));
+    }
+  }
+
+  /* Copy bucket values from another histogram */
+  void copy(Histogram &hist) {
+    // the two histogram bucket definition must match
+    if (getBucketSize() != hist.getBucketSize() ||
+        getMin() != hist.getMin() ||
+        getMax() != hist.getMax() ||
+        getNumBuckets() != hist.getNumBuckets() ) {
+      throw std::invalid_argument("Cannot copy from input histogram.");
+    }
+
+    for (int i = 0; i < buckets_.getNumBuckets(); i++) {
+      buckets_.getByIndex(i) = hist.buckets_.getByIndex(i);
+    }
+  }
+
   /* Returns the bucket size of each bucket in the histogram. */
   ValueType getBucketSize() const {
     return buckets_.getBucketSize();