// $Id$
//
-// Copyright (C) 2008
+// Copyright (C) 2008
// Fraunhofer Institute for Open Communication Systems (FOKUS)
// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
// 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)
{
namespace fmt = senf::format;
- os << boost::format("%s%-5d%|15t| %12.5g %19.5g %12.5g\n")
- % std::string(2*level,' ') % rank()
+ os << boost::format("%s%-5d%|15t| %12.5g %19.5g %12.5g\n")
+ % std::string(2*level,' ') % rank()
% fmt::eng(min()).setw() % fmt::eng(avg(),dev()).setw() % fmt::eng(max()).setw();
{
OutputMap::const_iterator i (outputs_.begin());
OutputMap::const_iterator i_end (outputs_.end());
for (; i != i_end; ++i)
os << boost::format(" %3d %12.5g %19.5g %12.5g\n")
- % i->second.n
- % fmt::eng(i->second.min).setw()
- % fmt::eng(i->second.avg, i->second.dev).setw()
+ % i->second.n
+ % fmt::eng(i->second.min).setw()
+ % fmt::eng(i->second.avg, i->second.dev).setw()
% fmt::eng(i->second.max).setw();
}
{
}
}
-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
#ifndef SENF_DISABLE_CONSOLE
namespace fty = senf::console::factory;
- dir.add("list", fty::BoundCommand(this,&Statistics::consoleList)
+ dir.add("list", fty::Command(&Statistics::consoleList, this)
.doc("List statistics collection intervals and current values.\n"
"\n"
"Columns:\n"
" AVG Last entered average value.\n"
" DEV Standard deviation of average value over the collector rank.\n"
" MAX Last entered maximum value.") );
- dir.add("collect", fty::BoundCommand(this, &Statistics::consoleCollect)
+ dir.add("collect", fty::Command(&Statistics::consoleCollect, this)
.doc("Add statistics collection groups. The argument gives a sequence of collector\n"
"ranks each building on the preceding collector:\n"
"\n"
"You may call collect multiple times. Any missing collection ranks will be\n"
"added.")
.arg("ranks","chain of collector ranks") );
- dir.add("output", fty::BoundCommand(this, &Statistics::consoleOutput)
+ dir.add("output", fty::Command(&Statistics::consoleOutput, this)
.doc("Generate statistics output. This statement will add an additional output\n"
"generator. This generator will be attached to the collector specified by\n"
"the {rank} parameter. This parameter is a chain of successive rank values\n"
for (; i != i_end; ++i)
stats = & (stats->collect(*i));
-
+
}
prefix_ boost::shared_ptr<senf::console::DirectoryNode>
StatisticsBase * stats (this);
std::vector<unsigned>::const_iterator i (ranks.begin());
std::vector<unsigned>::const_iterator const i_end (ranks.end());
-
+
try {
for (; i != i_end; ++i)
stats = &(*stats)[*i];
for (; i != i_end; ++i)
stats = & (stats->collect(*i));
-
+
return stats->output(window).dir().node().thisptr();
}
///////////////////////////////////////////////////////////////////////////
// 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;
}
}