move rateHelper() to detail/Stats.h
[folly.git] / folly / stats / BucketedTimeSeries.h
index f343c483e0d963d794c0d6098bab4dd42669efcb..22d8421dca8796a0c9a8150bce8478412b4917a8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012 Facebook, Inc.
+ * Copyright 2013 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -104,11 +104,29 @@ class BucketedTimeSeries {
 
   /*
    * Get the latest time that has ever been passed to update() or addValue().
+   *
+   * If no data has ever been added to this timeseries, 0 will be returned.
    */
   TimeType getLatestTime() const {
     return latestTime_;
   }
 
+  /*
+   * Get the time of the earliest data point stored in this timeseries.
+   *
+   * If no data has ever been added to this timeseries, 0 will be returned.
+   *
+   * If isAllTime() is true, this is simply the time when the first data point
+   * was recorded.
+   *
+   * For non-all-time data, the timestamp reflects the first data point still
+   * remembered.  As new data points are added, old data will be expired.
+   * getEarliestTime() returns the timestamp of the oldest bucket still present
+   * in the timeseries.  This will never be older than (getLatestTime() -
+   * duration()).
+   */
+  TimeType getEarliestTime() const;
+
   /*
    * Return the number of buckets.
    */
@@ -170,6 +188,16 @@ class BucketedTimeSeries {
    */
   TimeType elapsed() const;
 
+  /*
+   * Get the amount of time tracked by this timeseries, between the specified
+   * start and end times.
+   *
+   * If the timeseries contains data for the entire time range specified, this
+   * simply returns (end - start).  However, if start is earlier than
+   * getEarliestTime(), this returns (end - getEarliestTime()).
+   */
+  TimeType elapsed(TimeType start, TimeType end) const;
+
   /*
    * Return the sum of all the data points currently tracked by this
    * BucketedTimeSeries.
@@ -203,7 +231,7 @@ class BucketedTimeSeries {
    */
   template <typename ReturnType=double>
   ReturnType avg() const {
-    return total_.avg<ReturnType>();
+    return total_.template avg<ReturnType>();
   }
 
   /*
@@ -243,8 +271,8 @@ class BucketedTimeSeries {
    *
    * Note that data outside of the timeseries duration will no longer be
    * available for use in the estimation.  Specifying a start time earlier than
-   * (getLatestTime() - elapsed()) will not have much effect, since only data
-   * points after that point in time will be counted.
+   * getEarliestTime() will not have much effect, since only data points after
+   * that point in time will be counted.
    *
    * Note that the value returned is an estimate, and may not be precise.
    */
@@ -277,7 +305,8 @@ class BucketedTimeSeries {
   template <typename ReturnType=double, typename Interval=TimeType>
   ReturnType rate(TimeType start, TimeType end) const {
     ValueType intervalSum = sum(start, end);
-    return rateHelper<ReturnType, Interval>(intervalSum, end - start);
+    TimeType interval = elapsed(start, end);
+    return rateHelper<ReturnType, Interval>(intervalSum, interval);
   }
 
   /*
@@ -290,7 +319,8 @@ class BucketedTimeSeries {
   template <typename ReturnType=double, typename Interval=TimeType>
   ReturnType countRate(TimeType start, TimeType end) const {
     uint64_t intervalCount = count(start, end);
-    return rateHelper<ReturnType, Interval>(intervalCount, end - start);
+    TimeType interval = elapsed(start, end);
+    return rateHelper<ReturnType, Interval>(intervalCount, interval);
   }
 
   /*
@@ -342,26 +372,8 @@ class BucketedTimeSeries {
  private:
   template <typename ReturnType=double, typename Interval=TimeType>
   ReturnType rateHelper(ReturnType numerator, TimeType elapsed) const {
-    if (elapsed == TimeType(0)) {
-      return 0;
-    }
-
-    // Use std::chrono::duration_cast to convert between the native
-    // duration and the desired interval.  However, convert the rates,
-    // rather than just converting the elapsed duration.  Converting the
-    // elapsed time first may collapse it down to 0 if the elapsed interval
-    // is less than the desired interval, which will incorrectly result in
-    // an infinite rate.
-    typedef std::chrono::duration<
-        ReturnType, std::ratio<TimeType::period::den,
-                               TimeType::period::num>> NativeRate;
-    typedef std::chrono::duration<
-        ReturnType, std::ratio<Interval::period::den,
-                               Interval::period::num>> DesiredRate;
-
-    NativeRate native(numerator / elapsed.count());
-    DesiredRate desired = std::chrono::duration_cast<DesiredRate>(native);
-    return desired.count();
+    return detail::rateHelper<ReturnType, TimeType, Interval>(numerator,
+                                                              elapsed);
   }
 
   ValueType rangeAdjust(TimeType bucketStart, TimeType nextBucketStart,