Replace ad-hoc or locally defined power-of-2 tests
[gem5.git] / base / statistics.cc
index abebcae53d72c20fa95ab477465ad6eea22e7bdf..c9756464176d5e5a5530024ce13cc1b8a20f8f95 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2003-2005 The Regents of The University of Michigan
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  */
 
 #include <iomanip>
-#include <iostream>
+#include <fstream>
 #include <list>
 #include <map>
 #include <string>
 #include <sstream>
 
-#include <math.h>
-
+#include "base/callback.hh"
 #include "base/cprintf.hh"
-#include "base/intmath.hh"
+#include "base/hostinfo.hh"
 #include "base/misc.hh"
 #include "base/statistics.hh"
 #include "base/str.hh"
-#include "sim/universe.hh"
-
-#ifdef __M5_NAN
-float
-__nan()
-{
-    union {
-        uint32_t ui;
-        float f;
-    } nan;
-
-    nan.ui = 0x7fc00000;
-    return nan.f;
-}
-#endif
-
-#ifdef STAT_DEBUG
-static int total_stats = 0;
-#endif
+#include "base/time.hh"
+#include "base/trace.hh"
+#include "base/stats/statdb.hh"
+#include "config/stats_binning.hh"
 
 using namespace std;
 
-// This is a hack to get this parameter from the old stats package.
-namespace Statistics {
-bool PrintDescriptions = true;
-
-namespace Detail {
-/**
- * Struct to contain a name and description of statistic subfield.
- */
-struct SubData
-{
-    /** Subfield name. */
-    string name;
-    /** Subfield desc. */
-    string desc;
-};
-
-/**
- * Struct to contain print data of a Stat.
- */
-struct StatData
-{
-    /**
-     * Create this struct.
-     */
-    StatData();
-    /**
-     * Destructor.
-     */
-    ~StatData();
-
-    /** True if the stat has been initialized. */
-    bool init;
-    /** True if the stat should be printed. */
-    bool print;
-    /** The name of the stat. */
-    string name;
-    /** Names and descriptions of subfields. */
-    vector<SubData> *subdata;
-    /** The description of the stat. */
-    string desc;
-    /** The display precision. */
-    int precision;
-    /** The formatting flags. */
-    FormatFlags flags;
-    /** A pointer to a prerequisite Stat. */
-    const Stat *prereq;
-};
+namespace Stats {
 
-StatData::StatData()
-    : init(false), print(false), subdata(NULL), precision(-1), flags(none),
-      prereq(NULL)
+StatData *
+DataAccess::find() const
 {
+    return Database::find(const_cast<void *>((const void *)this));
 }
 
-StatData::~StatData()
+const StatData *
+getStatData(const void *stat)
 {
-    if (subdata)
-        delete subdata;
+    return Database::find(const_cast<void *>(stat));
 }
 
-class Database
-{
-  private:
-    Database(const Database &) {}
-
-  private:
-    typedef list<Stat *> list_t;
-    typedef map<const Stat *, StatData *> map_t;
-
-    list_t allStats;
-    list_t printStats;
-    map_t map;
-
-  public:
-    Database();
-    ~Database();
-
-    void dump(ostream &stream);
-
-    StatData *find(const Stat *stat);
-    void check();
-    void regStat(Stat *stat);
-    StatData *print(Stat *stat);
-};
-
-Database::Database()
-{}
-
-Database::~Database()
-{}
-
 void
-Database::dump(ostream &stream)
+DataAccess::map(StatData *data)
 {
-    list_t::iterator i = printStats.begin();
-    list_t::iterator end = printStats.end();
-
-    while (i != end) {
-        Stat *stat = *i;
-        if (stat->dodisplay())
-            stat->display(stream);
-        ++i;
-    }
+    Database::regStat(this, data);
 }
 
 StatData *
-Database::find(const Stat *stat)
+DataAccess::statData()
 {
-    map_t::const_iterator i = map.find(stat);
-
-    if (i == map.end())
-        return NULL;
+    StatData *ptr = find();
+    assert(ptr);
+    return ptr;
+}
 
-    return (*i).second;
+const StatData *
+DataAccess::statData() const
+{
+    const StatData *ptr = find();
+    assert(ptr);
+    return ptr;
 }
 
 void
-Database::check()
+DataAccess::setInit()
 {
-    list_t::iterator i = allStats.begin();
-    list_t::iterator end = allStats.end();
-
-    while (i != end) {
-        Stat *stat = *i;
-        StatData *data = find(stat);
-        if (!data || !data->init) {
-#ifdef STAT_DEBUG
-            cprintf("this is stat number %d\n",(*i)->number);
-#endif
-            panic("Not all stats have been initialized");
-        }
-
-        if (data->print) {
-            if (data->name.empty())
-                panic("all printable stats must be named");
-
-            list_t::iterator j = printStats.insert(printStats.end(), *i);
-            inplace_merge(printStats.begin(), j,
-                          printStats.end(), Stat::less);
-        }
-
-        ++i;
-    }
+    statData()->flags |= init;
 }
 
 void
-Database::regStat(Stat *stat)
+DataAccess::setPrint()
 {
-    if (map.find(stat) != map.end())
-        panic("shouldn't register stat twice!");
+    Database::regPrint(this);
+}
 
-    allStats.push_back(stat);
+StatData::StatData()
+    : flags(none), precision(-1), prereq(0)
+{
+    static int count = 0;
+    id = count++;
+}
 
-    StatData *data = new StatData;
-    bool success = (map.insert(make_pair(stat, data))).second;
-    assert(map.find(stat) != map.end());
-    assert(success && "this should never fail");
+StatData::~StatData()
+{
 }
 
 bool
-Stat::less(Stat *stat1, Stat *stat2)
+StatData::less(StatData *stat1, StatData *stat2)
 {
-    const string &name1 = stat1->myname();
-    const string &name2 = stat2->myname();
+    const string &name1 = stat1->name;
+    const string &name2 = stat2->name;
 
     vector<string> v1;
     vector<string> v2;
@@ -247,599 +131,227 @@ Stat::less(Stat *stat1, Stat *stat2)
     return false;
 }
 
-StatData *
-Database::print(Stat *stat)
+bool
+StatData::baseCheck() const
 {
-    StatData *data = find(stat);
-    assert(data);
+    if (!(flags & init)) {
+#ifdef DEBUG
+        cprintf("this is stat number %d\n", id);
+#endif
+        panic("Not all stats have been initialized");
+        return false;
+    }
 
-    data->print = true;
+    if ((flags & print) && name.empty()) {
+        panic("all printable stats must be named");
+        return false;
+    }
 
-    return data;
+    return true;
 }
 
-Database &
-StatDB()
-{
-    static Database db;
-    return db;
-}
-
-Stat::Stat(bool reg)
-{
-#if 0
-    // This assert can help you find that pesky stat.
-    assert(this != (void *)0xbffff5c0);
-#endif
-
-    if (reg)
-        StatDB().regStat(this);
-#ifdef STAT_DEBUG
-    number = ++total_stats;
-    cprintf("I'm stat number %d\n",number);
-#endif
-}
 
 void
-Stat::setInit()
-{ mydata()->init = true; }
-
-StatData *
-Stat::mydata()
-{
-    StatData *data = StatDB().find(this);
-    assert(data);
-
-    return data;
-}
-
-const StatData *
-Stat::mydata() const
+FormulaBase::result(VResult &vec) const
 {
-    StatData *data = StatDB().find(this);
-    assert(data);
-
-    return data;
+    if (root)
+        vec = root->result();
 }
 
-const SubData *
-Stat::mysubdata(int index) const
+Result
+FormulaBase::total() const
 {
-    assert(index >= 0);
-    if (index >= size())
-        return NULL;
-
-    const StatData *data = this->mydata();
-    if (!data->subdata || data->subdata->size() <= index)
-        return NULL;
-
-    return &(*data->subdata)[index];
+    return root ? root->total() : 0.0;
 }
 
-SubData *
-Stat::mysubdata_create(int index)
+size_t
+FormulaBase::size() const
 {
-    int size = this->size();
-    assert(index >= 0 && (size == 0 || size > 0 && index < size));
-
-    StatData *data = this->mydata();
-    if (!data->subdata) {
-        if (!data->subdata) {
-            if (size == 0)
-                size = index + 1;
-
-            data->subdata = new vector<SubData>(size);
-        }
-    } else if (data->subdata->size() <= index)
-            data->subdata->resize(index + 1);
-
-    SubData *sd = &(*data->subdata)[index];
-    assert(sd);
-
-    return sd;
+    if (!root)
+        return 0;
+    else
+        return root->size();
 }
 
-string
-Stat::myname() const
-{ return mydata()->name; }
-
-string
-Stat::mysubname(int index) const
+bool
+FormulaBase::binned() const
 {
-    const SubData *sd = mysubdata(index);
-    return sd ? sd->name : "";
+    return root && root->binned();
 }
 
-string
-Stat::mydesc() const
-{ return mydata()->desc; }
-
-string
-Stat::mysubdesc(int index) const
+void
+FormulaBase::reset()
 {
-    const SubData *sd = mysubdata(index);
-    return sd ? sd->desc : "";
 }
 
-int
-Stat::myprecision() const
-{ return mydata()->precision; }
-
-FormatFlags
-Stat::myflags() const
-{ return mydata()->flags; }
-
 bool
-Stat::dodisplay() const
-{ return !mydata()->prereq || !mydata()->prereq->zero(); }
-
-StatData *
-Stat::print()
+FormulaBase::zero() const
 {
-    StatData *data = StatDB().print(this);
-    assert(data && data->init);
-
-    return data;
+    VResult vec;
+    result(vec);
+    for (int i = 0; i < vec.size(); ++i)
+        if (vec[i] != 0.0)
+            return false;
+    return true;
 }
 
-Stat &
-Stat::name(const string &name)
+void
+FormulaBase::update(StatData *)
 {
-    print()->name = name;
-    return *this;
 }
 
-Stat &
-Stat::desc(const string &desc)
+string
+FormulaBase::str() const
 {
-    print()->desc = desc;
-    return *this;
+    return root ? root->str() : "";
 }
 
-Stat &
-Stat::precision(int precision)
+Formula::Formula()
 {
-    print()->precision = precision;
-    return *this;
+    setInit();
 }
 
-Stat &
-Stat::flags(FormatFlags flags)
+Formula::Formula(Temp r)
 {
-    if (flags & __reserved)
-        panic("Cannot set reserved flags!\n");
-
-    print()->flags |= flags;
-    return *this;
+    root = r;
+    assert(size());
 }
 
-Stat &
-Stat::prereq(const Stat &prereq)
+const Formula &
+Formula::operator=(Temp r)
 {
-    print()->prereq = &prereq;
+    assert(!root && "Can't change formulas");
+    root = r;
+    assert(size());
     return *this;
 }
 
-Stat &
-Stat::subname(int index, const string &name)
+const Formula &
+Formula::operator+=(Temp r)
 {
-    print();
-    mysubdata_create(index)->name = name;
-    return *this;
-}
-Stat &
-Stat::subdesc(int index, const string &desc)
-{
-    print();
-    mysubdata_create(index)->desc = desc;
+    if (root)
+        root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
+    else
+        root = r;
+    assert(size());
     return *this;
 }
 
-bool
-ScalarStat::zero() const
+MainBin::MainBin(const string &name)
+    : _name(name), mem(NULL), memsize(-1)
 {
-    return val() == 0.0;
+    Database::regBin(this, name);
 }
 
-bool
-VectorStat::zero() const
+MainBin::~MainBin()
 {
-    return val()[0] == 0.0;
-}
-
-string
-ValueToString(result_t value, int precision)
-{
-    stringstream val;
-
-    if (!isnan(value)) {
-        if (precision != -1)
-            val.precision(precision);
-        else if (value == rint(value))
-            val.precision(0);
-
-        val.unsetf(ios::showpoint);
-        val.setf(ios::fixed);
-        val << value;
-    } else {
-#ifndef STAT_DISPLAY_COMPAT
-        val << "no value";
-#else
-        val << "<err: div-0>";
-#endif
-    }
-
-    return val.str();
-}
-
-void
-PrintOne(ostream &stream, result_t value,
-         const string &name, const string &desc, int precision,
-         FormatFlags flags, result_t pdf = NAN, result_t cdf = NAN)
-{
-    if (flags & nozero && value == 0.0 ||
-        flags & nonan && isnan(value))
-        return;
-
-    stringstream pdfstr, cdfstr;
-
-    if (!isnan(pdf))
-        ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
-
-    if (!isnan(cdf))
-        ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
-
-#ifdef STAT_DISPLAY_COMPAT
-    if (flags & __substat) {
-        ccprintf(stream, "%32s%12s%10s%10s", name,
-                 ValueToString(value, precision),
-                 pdfstr, cdfstr);
-    } else
-#endif
-    {
-        ccprintf(stream, "%-40s%12s%10s%10s", name,
-                 ValueToString(value, precision), pdfstr, cdfstr);
-    }
-
-    if (PrintDescriptions) {
-        if (!desc.empty())
-            ccprintf(stream, " # %s", desc);
-    }
-    stream << endl;
-}
-
-void
-ScalarStat::display(ostream &stream) const
-{
-    PrintOne(stream, val(), myname(), mydesc(), myprecision(), myflags());
+    if (mem)
+        delete [] mem;
 }
 
-void
-VectorStat::display(ostream &stream) const
+char *
+MainBin::memory(off_t off)
 {
-    bool have_subname = false;
-    bool have_subdesc = false;
-    int size = this->size();
-    for (int i = 0; i < size; ++i) {
-        if (!mysubname(i).empty())
-            have_subname = true;
-        if (!mysubdesc(i).empty())
-            have_subdesc = true;
-    }
+    if (memsize == -1)
+        memsize = ceilPow2((size_t) offset());
 
-    vector<string> *subnames = 0;
-    vector<string> *subdescs = 0;
-    if (have_subname) {
-        subnames = new vector<string>(size);
-        for (int i = 0; i < size; ++i)
-            (*subnames)[i] = mysubname(i);
-    }
-    if (have_subdesc) {
-        subdescs = new vector<string>(size);
-        for (int i = 0; i < size; ++i)
-            (*subdescs)[i] = mysubdesc(i);
+    if (!mem) {
+        mem = new char[memsize];
+        memset(mem, 0, memsize);
     }
 
-    VectorDisplay(stream, myname(), subnames, mydesc(), subdescs,
-                  myprecision(), myflags(), val(), total());
+    assert(offset() <= size());
+    return mem + off;
 }
 
-#ifndef STAT_DISPLAY_COMPAT
-#define NAMESEP "::"
-#else
-#define NAMESEP "_"
-#endif
-
-#ifndef STAT_DISPLAY_COMPAT
 void
-VectorDisplay(std::ostream &stream,
-              const std::string &myname,
-              const std::vector<std::string> *mysubnames,
-              const std::string &mydesc,
-              const std::vector<std::string> *mysubdescs,
-              int myprecision, FormatFlags myflags,
-              const rvec_t &vec, result_t mytotal)
+check()
 {
-    int _size = vec.size();
-    result_t _total = 0.0;
-    result_t _pdf, _cdf = 0.0;
+    typedef Database::stat_list_t::iterator iter_t;
 
-    if (myflags & (pdf | cdf)) {
-        for (int i = 0; i < _size; ++i) {
-            _total += vec[i];
-        }
+    iter_t i, end = Database::stats().end();
+    for (i = Database::stats().begin(); i != end; ++i) {
+        StatData *data = *i;
+        assert(data);
+        if (!data->check() || !data->baseCheck())
+            panic("stat check failed for %s\n", data->name);
     }
 
-    if (_size == 1) {
-        PrintOne(stream, vec[0], myname, mydesc, myprecision, myflags);
-    } else {
-        for (int i = 0; i < _size; ++i) {
-            string subname;
-            if (mysubnames) {
-                subname = (*mysubnames)[i];
-                if (subname.empty())
-                    continue;
-            } else {
-                subname = to_string(i);
-            }
-
-            string name = myname + NAMESEP + subname;
-            if (!(myflags & pdf))
-                PrintOne(stream, vec[i], name, mydesc, myprecision, myflags);
-            else {
-                _pdf = vec[i] / _total;
-                _cdf += _pdf;
-                PrintOne(stream, vec[i], name, mydesc, myprecision, myflags,
-                         _pdf, _cdf);
-            }
-        }
-
-        if (myflags & total)
-            PrintOne(stream, mytotal, myname + NAMESEP + "total",
-                     mydesc, myprecision, myflags);
+    int j = 0;
+    for (i = Database::stats().begin(); i != end; ++i) {
+        StatData *data = *i;
+        if (!(data->flags & print))
+            data->name = "__Stat" + to_string(j++);
     }
-}
-#else
-void
-VectorDisplay(std::ostream &stream,
-              const std::string &myname,
-              const std::vector<std::string> *mysubnames,
-              const std::string &mydesc,
-              const std::vector<std::string> *mysubdescs,
-              int myprecision, FormatFlags myflags,
-              const rvec_t &vec, result_t mytotal)
-{
-    int _size = vec.size();
-    result_t _total = 0.0;
-    result_t _pdf, _cdf = 0.0;
 
-    if (myflags & (pdf | cdf)) {
-        for (int i = 0; i < _size; ++i) {
-            _total += vec[i];
-        }
-    }
+    Database::stats().sort(StatData::less);
 
-    if (_size == 1) {
-        PrintOne(stream, vec[0], myname, mydesc, myprecision, myflags);
-    } else {
-        if (myflags & total)
-            PrintOne(stream, mytotal, myname, mydesc, myprecision, myflags);
-
-        if (myflags & dist) {
-            ccprintf(stream, "%s.start_dist\n", myname);
-            for (int i = 0; i < _size; ++i) {
-                string subname, subdesc;
-                subname = to_string(i);
-                if (mysubnames) {
-                    if (!subname.empty()) {
-                        subname = (*mysubnames)[i];
-                    }
-                }
-                if (mysubdescs) {
-                    subdesc = (*mysubdescs)[i];
-                }
-                if (!(myflags & (pdf | cdf))) {
-                    PrintOne(stream, vec[i], subname, subdesc, myprecision,
-                             myflags | __substat);
-                } else {
-                    if (_total) {
-                        _pdf = vec[i] / _total;
-                        _cdf += _pdf;
-                    } else {
-                        _pdf = _cdf = 0.0;
-                    }
-                    if (!(myflags & cdf)) {
-                        PrintOne(stream, vec[i], subname, subdesc, myprecision,
-                                 myflags | __substat, _pdf);
-                    } else {
-                        PrintOne(stream, vec[i], subname, subdesc, myprecision,
-                                 myflags | __substat, _pdf, _cdf);
-                    }
-                }
-            }
-            ccprintf(stream, "%s.end_dist\n", myname);
-        } else {
-            for (int i = 0; i < _size; ++i) {
-                string subname;
-                if (mysubnames) {
-                    subname = (*mysubnames)[i];
-                    if (subname.empty())
-                        continue;
-                } else {
-                    subname = to_string(i);
-                }
-
-                string name = myname + NAMESEP + subname;
-                if (!(myflags & pdf)) {
-                    PrintOne(stream, vec[i], name, mydesc, myprecision,
-                             myflags);
-                } else {
-                    if (_total) {
-                        _pdf = vec[i] / _total;
-                        _cdf += _pdf;
-                    } else {
-                        _pdf = _cdf = 0.0;
-                    }
-                    _pdf = vec[i] / _total;
-                    _cdf += _pdf;
-                    PrintOne(stream, vec[i], name, mydesc, myprecision,
-                             myflags, _pdf, _cdf);
-                }
-            }
-        }
+#if STATS_BINNING
+    if (MainBin::curBin() == NULL) {
+        static MainBin mainBin("main bin");
+        mainBin.activate();
     }
-}
 #endif
 
-#ifndef STAT_DISPLAY_COMPAT
-void
-DistDisplay(ostream &stream, const string &name, const string &desc,
-            int precision, FormatFlags flags,
-            result_t min_val, result_t max_val,
-            result_t underflow, result_t overflow,
-            const rvec_t &vec, int min, int max, int bucket_size, int size);
-{
-    assert(size == vec.size());
-
-    result_t total = 0.0;
-    result_t pdf, cdf = 0.0;
-
-    total += underflow;
-    for (int i = 0; i < size; ++i)
-        total += vec[i];
-    total += overflow;
-
-    pdf = underflow / total;
-    cdf += pdf;
-
-    PrintOne(stream, underflow, name + NAMESEP + "underflow", desc,
-             precision, myflags, pdf, cdf);
+    if (i == end)
+        return;
 
-    for (int i = 0; i < size; ++i) {
-        stringstream namestr;
-        namestr << name;
+    iter_t last = i;
+    ++i;
 
-        int low = i * bucket_size + min;
-        int high = ::std::min((i + 1) * bucket_size + min - 1, max);
-        namestr << low;
-        if (low < high)
-            namestr << "-" << high;
+    for (i = Database::stats().begin(); i != end; ++i) {
+        if ((*i)->name == (*last)->name)
+            panic("same name used twice! name=%s\n", (*i)->name);
 
-        pdf = vec[i] / total;
-        cdf += pdf;
-        PrintOne(stream, vec[i], namestr.str(), desc, precision, myflags,
-                 pdf, cdf);
+        last = i;
     }
-
-    pdf = overflow / total;
-    cdf += pdf;
-    PrintOne(stream, overflow, name + NAMESEP + "overflow", desc,
-             precision, myflags, pdf, cdf);
-    PrintOne(stream, total, name + NAMESEP + "total", desc,
-             precision, myflags);
 }
-#else
-void
-DistDisplay(ostream &stream, const string &name, const string &desc,
-            int precision, FormatFlags flags,
-            result_t min_val, result_t max_val,
-            result_t underflow, result_t overflow,
-            const rvec_t &vec, int min, int max, int bucket_size, int size)
-{
-    assert(size == vec.size());
-    string blank;
 
-    result_t total = 0.0;
-
-    total += underflow;
-    for (int i = 0; i < size; ++i)
-        total += vec[i];
-    total += overflow;
-
-    ccprintf(stream, "%-42s", name + ".start_dist");
-    if (PrintDescriptions && !desc.empty())
-        ccprintf(stream, "                     # %s", desc);
-    stream << endl;
-
-    PrintOne(stream, total, name + ".samples", blank, precision, flags);
-    PrintOne(stream, min_val, name + ".min_value", blank, precision, flags);
-
-    if (underflow > 0)
-        PrintOne(stream, min_val, name + ".underflows", blank, precision,
-                 flags);
-
-    int _min;
-    result_t _pdf, _cdf, mypdf, mycdf;
-
-    _cdf = 0.0;
-    for (int i = 0; i < size; ++i) {
-        if (flags & nozero && vec[i] == 0.0 ||
-            flags & nonan && isnan(vec[i]))
-            return;
-
-        _min = i * bucket_size + min;
-        _pdf = vec[i] / total * 100.0;
-        _cdf += _pdf;
-
-        mypdf = (flags & pdf) ? _pdf : NAN;
-        mycdf = (flags & cdf) ? _cdf : NAN;
-
-        PrintOne(stream, vec[i], ValueToString(_min, 0), blank, precision,
-                 flags | __substat, mypdf, mycdf);
-    }
-
-    if (overflow > 0)
-        PrintOne(stream, overflow, name + ".overflows", blank, precision,
-                 flags);
-    PrintOne(stream, max_val, name + ".max_value", blank, precision, flags);
-    ccprintf(stream, "%s.end_dist\n\n", name);
-}
-#endif
+CallbackQueue resetQueue;
 
 void
-FancyDisplay(ostream &stream, const string &name, const string &desc,
-             int precision, FormatFlags flags, result_t mean,
-             result_t variance)
-{
-    result_t stdev = isnan(variance) ? NAN : sqrt(variance);
-    PrintOne(stream, mean, name + NAMESEP + "mean", desc, precision, flags);
-    PrintOne(stream, stdev, name + NAMESEP + "stdev", desc, precision, flags);
-}
-
-BinBase::BinBase(size_t size)
-    : memsize(CeilPow2(size)), mem(NULL)
-{
-}
-
-BinBase::~BinBase()
-{
-    if (mem)
-        delete [] mem;
-}
-
-char *
-BinBase::memory()
+reset()
 {
-    if (!mem) {
-        mem = new char[memsize];
-        memset(mem, 0, memsize);
+    // reset non-binned stats
+    Database::stat_list_t::iterator i = Database::stats().begin();
+    Database::stat_list_t::iterator end = Database::stats().end();
+    while (i != end) {
+        StatData *data = *i;
+        if (!data->binned())
+            data->reset();
+        ++i;
     }
 
-    return mem;
-}
+    // save the bin so we can go back to where we were
+    MainBin *orig = MainBin::curBin();
+
+    // reset binned stats
+    Database::bin_list_t::iterator bi = Database::bins().begin();
+    Database::bin_list_t::iterator be = Database::bins().end();
+    while (bi != be) {
+        MainBin *bin = *bi;
+        bin->activate();
+
+        i = Database::stats().begin();
+        while (i != end) {
+            StatData *data = *i;
+            if (data->binned())
+                data->reset();
+            ++i;
+        }
+        ++bi;
+    }
 
-} // namespace Detail
+    // restore bin
+    MainBin::curBin() = orig;
 
-void
-check()
-{
-    Detail::StatDB().check();
+    resetQueue.process();
 }
 
 void
-dump(ostream &stream)
+registerResetCallback(Callback *cb)
 {
-    Detail::StatDB().dump(stream);
+    resetQueue.add(cb);
 }
 
-} // namespace Statistics
+/* namespace Stats */ }