Utils: Aggregate statistics submit interface
g0dil [Fri, 7 May 2010 08:46:25 +0000 (08:46 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1627 270642c3-0616-0410-b53a-bc976706d245

senf/Utils/Statistics.cc
senf/Utils/Statistics.cci
senf/Utils/Statistics.hh

index 01122b2..2fe9334 100644 (file)
@@ -28,6 +28,7 @@
 
 // Custom includes
 #include <cmath>
+#include <cstdlib>
 #include <sstream>
 #include <senf/Utils/Console/Console.hh>
 #include <senf/Utils/Format.hh>
 ///////////////////////////////////////////////////////////////////////////
 // senf::StatisticsBase
 
-prefix_ void senf::StatisticsBase::enter(float min, float avg, float max, float dev)
+prefix_ void senf::StatisticsBase::enter(unsigned n, float min, float avg, float max, float dev)
 {
     min_ = min;
     avg_ = avg;
     max_ = max;
     dev_ = dev;
-    generateOutput();
-    signalChildren();
+    for (unsigned i (0); i < n; ++i)
+        generateOutput();
+    Children::iterator i (children_.begin());
+    Children::iterator const i_end  (children_.end());
+    for (; i != i_end; ++i)
+        i->second.enter(n, min_, avg_, max_, dev_);
 }
 
 prefix_ senf::Collector & senf::StatisticsBase::operator[](unsigned rank)
@@ -136,14 +141,6 @@ prefix_ void senf::StatisticsBase::generateOutput()
     }
 }
 
-prefix_ void senf::StatisticsBase::signalChildren()
-{
-    Children::iterator i (children_.begin());
-    Children::iterator const i_end  (children_.end());
-    for (; i != i_end; ++i)
-        i->second.enter(min_, avg_, max_, dev_);
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // senf::Statistics
 
@@ -266,21 +263,37 @@ prefix_ std::string senf::Statistics::v_path()
 ///////////////////////////////////////////////////////////////////////////
 // senf::Collector
 
-prefix_ void senf::Collector::enter(float min, float avg, float max, float dev)
+prefix_ void senf::Collector::enter(unsigned n, float min, float avg, float max, float dev)
 {
-    accSum_ += avg;
-    accSumSq_ += avg*avg + dev*dev;
     if (min < accMin_) accMin_ = min;
     if (max > accMax_) accMax_ = max;
-    if (++i_ >= rank_) {
-        float accAvg (accSum_ / i_);
-        float accDev (std::sqrt(std::max(0.0f,accSumSq_ / i_ - accAvg*accAvg)));
-        StatisticsBase::enter(accMin_, accAvg, accMax_, accDev);
-        i_ = 0;
+
+    if (i_ + n >= rank_) {
+        accSum_ += (rank_-i_)*avg;
+        accSumSq_ += (rank_-i_)*(rank_-i_)*(avg*avg + dev*dev);
+        float accAvg (accSum_ / rank_);
+        float accDev (std::sqrt(std::max(0.0f,accSumSq_ / rank_ - accAvg*accAvg)));
+        StatisticsBase::enter(1, accMin_, accAvg, accMax_, accDev);
         accMin_ = FLT_MAX;
         accSum_ = 0.0f;
         accSumSq_ = 0.0f;
         accMax_ = -FLT_MAX;
+        n -= (rank_ - i_);
+        i_ = 0;
+
+        if (n >= rank_) {
+            std::div_t d (std::div(int(n), int(rank_)));
+            StatisticsBase::enter(d.quot, min, avg, max, dev);
+            n = d.rem;
+        }
+    }
+
+    if (n>0) {
+        accSum_ += n*avg;
+        accSumSq_ += n*n*(avg*avg+dev*dev);
+        i_ += n;
+        if (min < accMin_) accMin_ = min;
+        if (max > accMax_) accMax_ = max;
     }
 }
 
index 3b9ed9b..6fa454b 100644 (file)
@@ -170,14 +170,20 @@ senf::Collector::output(unsigned n)
 ///////////////////////////////////////////////////////////////////////////
 // senf::Statistics
 
+prefix_ void senf::Statistics::operator()(unsigned n, float min, float avg, float max,
+                                          float dev)
+{
+    enter(n, min, avg, max, dev);
+}
+
 prefix_ void senf::Statistics::operator()(float min, float avg, float max, float dev)
 {
-    enter(min, avg, max, dev);
+    enter(1, min, avg, max, dev);
 }
 
 prefix_ void senf::Statistics::operator()(float value, float dev)
 {
-    enter(value, value, value, dev);
+    enter(1, value, value, value, dev);
 }
 
 prefix_ senf::StatisticsBase::OutputProxy<senf::Statistics>
index b4cf0bf..3ac5d43 100644 (file)
@@ -228,14 +228,13 @@ namespace senf {
     protected:
         StatisticsBase();
         virtual ~StatisticsBase();
-        void enter(float min, float avg, float max, float dev);
+        void enter(unsigned n, float min, float avg, float max, float dev);
 
     private:
         virtual Statistics & v_base() = 0;
         virtual std::string v_path() const = 0;
 
         void generateOutput();
-        void signalChildren();
 
         float min_;
         float avg_;
@@ -420,24 +419,40 @@ namespace senf {
 
         Statistics();
 
-        void operator()(float min, float avg, float max, float dev=0.0f);
+        void operator()(unsigned n, float min, float avg, float max, float dev);
                                         ///< Enter new data
-                                        /**< This member must be called whenever a new data value is
-                                             available. It is important to call this member \e
-                                             periodically. The frequency at which this member is
-                                             called defines the basic statistics time scale.
+                                        /**< This member must be called whenever new data is
+                                             available.
 
                                              If \a min and \a max values are not available, this
                                              member should be called with \a min, \a avg and \a max
-                                             set to the same value.
-
+                                             set to the same value. If no error estimate is
+                                             available, call with \a dev = 0.
+
+                                             In the most common case, this member is to be called
+                                             periodically and \a n will be 1 on all calls. The
+                                             interval, at which this member is called then defines
+                                             the statistics time scale.
+
+                                             Calling with \a n > 1 will submit the value \a n
+                                             times. This makes it possible to aggregate multiple
+                                             time slices into a single call. This does not change
+                                             the basic time scale but can change the number of
+                                             submits per unit time. If the basic time slice is
+                                             small, this allows to submit values almost arbitrarily
+                                             non-periodic.
+
+                                             \param[in] n number of time-slices
                                              \param[in] min minimal data value since last call
                                              \param[in] avg average data value since last call
                                              \param[in] max maximal data values since last call
                                              \param[in] dev standard deviation of avg value */
-
+        void operator()(float min, float avg, float max, float dev=0.0f);
+                                        ///< Same as operator() with \a n==1
+                                        /**< Provided so a Statistics instance can be directly used
+                                             as a signal target. */
         void operator()(float value, float dev=0.0f);
-                                        ///< Same as enter() with \a min == \a avg == \a max
+                                        ///< Same as operator() with \a min == \a avg == \a max
                                         /**< Provided so a Statistics instance can be directly used
                                              as a signal target. */
 
@@ -469,7 +484,7 @@ namespace senf {
 
     private:
         Collector(StatisticsBase * owner, unsigned rank);
-        void enter(float min, float avg, float max, float dev);
+        void enter(unsigned n, float min, float avg, float max, float dev);
         Statistics & v_base();
         std::string v_path() const;