stats: create an enable phase, and a prepare phase.

Enable more or less takes the place of check, but also allows stats to
do some other configuration.  Prepare moves all of the code that readies
a stat for dumping into a separate function in preparation for supporting
serialization of certain pieces of statistics data.
While we're at it, clean up the visitor code and some of the python code.
This commit is contained in:
Nathan Binkert 2009-03-05 19:09:53 -08:00
parent 9f45fbaaa6
commit 6f787e3d36
7 changed files with 214 additions and 161 deletions

View file

@ -32,6 +32,7 @@
#include <fstream> #include <fstream>
#include <list> #include <list>
#include <map> #include <map>
#include <set>
#include <string> #include <string>
#include "base/callback.hh" #include "base/callback.hh"
@ -174,6 +175,41 @@ Info::baseCheck() const
return true; return true;
} }
void
Info::enable()
{
}
void
VectorInfoBase::enable()
{
size_type s = size();
if (subnames.size() < s)
subnames.resize(s);
if (subdescs.size() < s)
subdescs.resize(s);
}
void
VectorDistInfoBase::enable()
{
size_type s = size();
if (subnames.size() < s)
subnames.resize(s);
if (subdescs.size() < s)
subdescs.resize(s);
}
void
Vector2dInfoBase::enable()
{
if (subnames.size() < x)
subnames.resize(x);
if (subdescs.size() < x)
subdescs.resize(x);
if (y_subnames.size() < y)
y_subnames.resize(y);
}
Formula::Formula() Formula::Formula()
{ {
@ -244,11 +280,6 @@ Formula::zero() const
return true; return true;
} }
void
Formula::update()
{
}
string string
Formula::str() const Formula::str() const
{ {
@ -256,7 +287,7 @@ Formula::str() const
} }
void void
check() enable()
{ {
typedef list<Info *>::iterator iter_t; typedef list<Info *>::iterator iter_t;
@ -277,17 +308,21 @@ check()
statsList().sort(Info::less); statsList().sort(Info::less);
if (i == end)
return;
iter_t last = i;
++i;
for (i = statsList().begin(); i != end; ++i) { for (i = statsList().begin(); i != end; ++i) {
if ((*i)->name == (*last)->name) Info *info = *i;
panic("same name used twice! name=%s\n", (*i)->name); info->enable();
}
}
last = i; void
prepare()
{
list<Info *>::iterator i = statsList().begin();
list<Info *>::iterator end = statsList().end();
while (i != end) {
Info *info = *i;
info->prepare();
++i;
} }
} }

View file

@ -122,6 +122,16 @@ class Info
virtual bool check() const = 0; virtual bool check() const = 0;
bool baseCheck() const; bool baseCheck() const;
/**
* Enable the stat for use
*/
virtual void enable();
/**
* Prepare the stat for dumping.
*/
virtual void prepare() = 0;
/** /**
* Reset the stat to the default state. * Reset the stat to the default state.
*/ */
@ -159,7 +169,13 @@ class InfoWrap : public Base
InfoWrap(Stat &stat) : s(stat) {} InfoWrap(Stat &stat) : s(stat) {}
bool check() const { return s.check(); } bool check() const { return s.check(); }
void prepare() { s.prepare(); }
void reset() { s.reset(); } void reset() { s.reset(); }
void
visit(Visit &visitor)
{
visitor.visit(*static_cast<Base *>(this));
}
bool zero() const { return s.zero(); } bool zero() const { return s.zero(); }
}; };
@ -169,7 +185,6 @@ class ScalarInfoBase : public Info
virtual Counter value() const = 0; virtual Counter value() const = 0;
virtual Result result() const = 0; virtual Result result() const = 0;
virtual Result total() const = 0; virtual Result total() const = 0;
void visit(Visit &visitor) { visitor.visit(*this); }
}; };
template <class Stat> template <class Stat>
@ -190,24 +205,14 @@ class VectorInfoBase : public Info
std::vector<std::string> subnames; std::vector<std::string> subnames;
std::vector<std::string> subdescs; std::vector<std::string> subdescs;
public:
void enable();
public: public:
virtual size_type size() const = 0; virtual size_type size() const = 0;
virtual const VCounter &value() const = 0; virtual const VCounter &value() const = 0;
virtual const VResult &result() const = 0; virtual const VResult &result() const = 0;
virtual Result total() const = 0; virtual Result total() const = 0;
void
update()
{
if (!subnames.empty()) {
size_type s = size();
if (subnames.size() < s)
subnames.resize(s);
if (subdescs.size() < s)
subdescs.resize(s);
}
}
}; };
template <class Stat> template <class Stat>
@ -237,14 +242,6 @@ class VectorInfo : public InfoWrap<Stat, VectorInfoBase>
} }
Result total() const { return this->s.total(); } Result total() const { return this->s.total(); }
void
visit(Visit &visitor)
{
this->update();
this->s.update();
visitor.visit(*this);
}
}; };
struct DistData struct DistData
@ -271,13 +268,6 @@ class DistInfo : public InfoWrap<Stat, DistInfoBase>
{ {
public: public:
DistInfo(Stat &stat) : InfoWrap<Stat, DistInfoBase>(stat) {} DistInfo(Stat &stat) : InfoWrap<Stat, DistInfoBase>(stat) {}
void
visit(Visit &visitor)
{
this->s.update();
visitor.visit(*this);
}
}; };
class VectorDistInfoBase : public Info class VectorDistInfoBase : public Info
@ -288,6 +278,7 @@ class VectorDistInfoBase : public Info
/** Names and descriptions of subfields. */ /** Names and descriptions of subfields. */
std::vector<std::string> subnames; std::vector<std::string> subnames;
std::vector<std::string> subdescs; std::vector<std::string> subdescs;
void enable();
protected: protected:
/** Local storage for the entry values, used for printing. */ /** Local storage for the entry values, used for printing. */
@ -295,17 +286,6 @@ class VectorDistInfoBase : public Info
public: public:
virtual size_type size() const = 0; virtual size_type size() const = 0;
void
update()
{
size_type s = size();
if (subnames.size() < s)
subnames.resize(s);
if (subdescs.size() < s)
subdescs.resize(s);
}
}; };
template <class Stat> template <class Stat>
@ -315,14 +295,6 @@ class VectorDistInfo : public InfoWrap<Stat, VectorDistInfoBase>
VectorDistInfo(Stat &stat) : InfoWrap<Stat, VectorDistInfoBase>(stat) {} VectorDistInfo(Stat &stat) : InfoWrap<Stat, VectorDistInfoBase>(stat) {}
size_type size() const { return this->s.size(); } size_type size() const { return this->s.size(); }
void
visit(Visit &visitor)
{
this->update();
this->s.update();
visitor.visit(*this);
}
}; };
class Vector2dInfoBase : public Info class Vector2dInfoBase : public Info
@ -339,13 +311,7 @@ class Vector2dInfoBase : public Info
/** Local storage for the entry values, used for printing. */ /** Local storage for the entry values, used for printing. */
mutable VCounter cvec; mutable VCounter cvec;
public: void enable();
void
update()
{
if (subnames.size() < x)
subnames.resize(x);
}
}; };
template <class Stat> template <class Stat>
@ -353,14 +319,6 @@ class Vector2dInfo : public InfoWrap<Stat, Vector2dInfoBase>
{ {
public: public:
Vector2dInfo(Stat &stat) : InfoWrap<Stat, Vector2dInfoBase>(stat) {} Vector2dInfo(Stat &stat) : InfoWrap<Stat, Vector2dInfoBase>(stat) {}
void
visit(Visit &visitor)
{
this->update();
this->s.update();
visitor.visit(*this);
}
}; };
class InfoAccess class InfoAccess
@ -382,7 +340,7 @@ class InfoAccess
/** /**
* Reset the stat to the default state. * Reset the stat to the default state.
*/ */
void reset() {} void reset() { }
/** /**
* @return true if this stat has a value and satisfies its * @return true if this stat has a value and satisfies its
@ -525,7 +483,7 @@ class DataWrapVec : public DataWrap<Derived, InfoType>
subname(off_type index, const std::string &name) subname(off_type index, const std::string &name)
{ {
Derived &self = this->self(); Derived &self = this->self();
Info *info = this->info(); Info *info = self.info();
std::vector<std::string> &subn = info->subnames; std::vector<std::string> &subn = info->subnames;
if (subn.size() <= index) if (subn.size() <= index)
@ -558,6 +516,17 @@ class DataWrapVec : public DataWrap<Derived, InfoType>
return this->self(); return this->self();
} }
void
prepare()
{
Derived &self = this->self();
Info *info = this->info();
size_t size = self.size();
for (off_type i = 0; i < size; ++i)
self.data(i)->prepare(info);
}
void void
reset() reset()
{ {
@ -657,6 +626,10 @@ class StatStor
* @return The value of this stat. * @return The value of this stat.
*/ */
Result result() const { return (Result)data; } Result result() const { return (Result)data; }
/**
* Prepare stat data for dumping or serialization
*/
void prepare(Info *info) { }
/** /**
* Reset stat value to default * Reset stat value to default
*/ */
@ -734,8 +707,7 @@ class AvgStor
Result Result
result() const result() const
{ {
total += current * (curTick - last); assert(last == curTick);
last = curTick;
return (Result)(total + current) / (Result)(curTick + 1); return (Result)(total + current) / (Result)(curTick + 1);
} }
@ -744,6 +716,16 @@ class AvgStor
*/ */
bool zero() const { return total == 0.0; } bool zero() const { return total == 0.0; }
/**
* Prepare stat data for dumping or serialization
*/
void
prepare(Info *info)
{
total += current * (curTick - last);
last = curTick;
}
/** /**
* Reset stat value to default * Reset stat value to default
*/ */
@ -863,11 +845,6 @@ class ScalarBase : public DataWrap<Derived, ScalarInfo>
*/ */
size_type size() const { return 1; } size_type size() const { return 1; }
/**
* Reset stat value to default
*/
void reset() { data()->reset(this->info()); }
Counter value() { return data()->value(); } Counter value() { return data()->value(); }
Result result() { return data()->result(); } Result result() { return data()->result(); }
@ -875,17 +852,22 @@ class ScalarBase : public DataWrap<Derived, ScalarInfo>
Result total() { return result(); } Result total() { return result(); }
bool zero() { return result() == 0.0; } bool zero() { return result() == 0.0; }
void reset() { data()->reset(this->info()); }
void prepare() { data()->prepare(this->info()); }
}; };
class ProxyInfo : public ScalarInfoBase class ProxyInfo : public ScalarInfoBase
{ {
public: public:
void visit(Visit &visitor) { visitor.visit(*this); }
std::string str() const { return to_string(value()); } std::string str() const { return to_string(value()); }
size_type size() const { return 1; } size_type size() const { return 1; }
bool check() const { return true; } bool check() const { return true; }
void reset() {} void prepare() { }
void reset() { }
bool zero() const { return value() == 0; } bool zero() const { return value() == 0; }
void visit(Visit &visitor) { visitor.visit(*this); }
}; };
template <class T> template <class T>
@ -950,6 +932,7 @@ class ValueBase : public DataWrap<Derived, ScalarInfo>
std::string str() const { return proxy->str(); } std::string str() const { return proxy->str(); }
bool zero() const { return proxy->zero(); } bool zero() const { return proxy->zero(); }
bool check() const { return proxy != NULL; } bool check() const { return proxy != NULL; }
void prepare() { }
void reset() { } void reset() { }
}; };
@ -1230,8 +1213,6 @@ class VectorBase : public DataWrapVec<Derived, VectorInfo>
assert (index >= 0 && index < size()); assert (index >= 0 && index < size());
return Proxy(this->self(), index); return Proxy(this->self(), index);
} }
void update() {}
}; };
template <class Stat> template <class Stat>
@ -1348,16 +1329,6 @@ class Vector2dBase : public DataWrapVec2d<Derived, Vector2dInfo>
delete [] reinterpret_cast<char *>(storage); delete [] reinterpret_cast<char *>(storage);
} }
void
update()
{
Info *info = this->info();
size_type size = this->size();
info->cvec.resize(size);
for (off_type i = 0; i < size; ++i)
info->cvec[i] = data(i)->value();
}
Derived & Derived &
init(size_type _x, size_type _y) init(size_type _x, size_type _y)
{ {
@ -1413,6 +1384,20 @@ class Vector2dBase : public DataWrapVec2d<Derived, Vector2dInfo>
#endif #endif
} }
void
prepare()
{
Info *info = this->info();
size_type size = this->size();
for (off_type i = 0; i < size; ++i)
data(i)->prepare(info);
info->cvec.resize(size);
for (off_type i = 0; i < size; ++i)
info->cvec[i] = data(i)->value();
}
/** /**
* Reset stat value to default * Reset stat value to default
*/ */
@ -1541,7 +1526,7 @@ class DistStor
} }
void void
update(Info *info, DistData &data) prepare(Info *info, DistData &data)
{ {
const Params *params = safe_cast<const Params *>(info->storageParams); const Params *params = safe_cast<const Params *>(info->storageParams);
@ -1630,14 +1615,6 @@ class FancyStor
samples += number; samples += number;
} }
void
update(Info *info, DistData &data)
{
data.sum = sum;
data.squares = squares;
data.samples = samples;
}
/** /**
* Return the number of entries in this stat, 1 * Return the number of entries in this stat, 1
* @return 1. * @return 1.
@ -1650,6 +1627,14 @@ class FancyStor
*/ */
bool zero() const { return samples == Counter(); } bool zero() const { return samples == Counter(); }
void
prepare(Info *info, DistData &data)
{
data.sum = sum;
data.squares = squares;
data.samples = samples;
}
/** /**
* Reset stat value to default * Reset stat value to default
*/ */
@ -1702,14 +1687,6 @@ class AvgFancy
squares += value * value; squares += value * value;
} }
void
update(Info *info, DistData &data)
{
data.sum = sum;
data.squares = squares;
data.samples = curTick;
}
/** /**
* Return the number of entries, in this case 1. * Return the number of entries, in this case 1.
* @return 1. * @return 1.
@ -1722,6 +1699,14 @@ class AvgFancy
*/ */
bool zero() const { return sum == Counter(); } bool zero() const { return sum == Counter(); }
void
prepare(Info *info, DistData &data)
{
data.sum = sum;
data.squares = squares;
data.samples = curTick;
}
/** /**
* Reset stat value to default * Reset stat value to default
*/ */
@ -1801,10 +1786,10 @@ class DistBase : public DataWrap<Derived, DistInfo>
bool zero() const { return data()->zero(); } bool zero() const { return data()->zero(); }
void void
update() prepare()
{ {
Info *info = this->info(); Info *info = this->info();
data()->update(info, info->data); data()->prepare(info, info->data);
} }
/** /**
@ -1900,24 +1885,21 @@ class VectorDistBase : public DataWrapVec<Derived, VectorDistInfo>
#endif #endif
} }
void
prepare()
{
Info *info = this->info();
size_type size = this->size();
info->data.resize(size);
for (off_type i = 0; i < size; ++i)
data(i)->prepare(info, info->data[i]);
}
bool bool
check() const check() const
{ {
return storage != NULL; return storage != NULL;
} }
void
update()
{
Derived &self = this->self();
Info *info = this->info();
size_type size = self.size();
info.data.resize(size);
for (off_type i = 0; i < size; ++i) {
data(i)->update(info, info.data[i]);
}
}
}; };
template <class Stat> template <class Stat>
@ -2589,14 +2571,6 @@ class FormulaInfo : public InfoWrap<Stat, FormulaInfoBase>
Result total() const { return this->s.total(); } Result total() const { return this->s.total(); }
VCounter &value() const { return cvec; } VCounter &value() const { return cvec; }
void
visit(Visit &visitor)
{
this->update();
this->s.update();
visitor.visit(*this);
}
std::string str() const { return this->s.str(); } std::string str() const { return this->s.str(); }
}; };
@ -2677,11 +2651,6 @@ class Formula : public DataWrapVec<Formula, FormulaInfo>
*/ */
bool zero() const; bool zero() const;
/**
*
*/
void update();
std::string str() const; std::string str() const;
}; };
@ -2876,11 +2845,6 @@ class Temp
* @} * @}
*/ */
void check();
void dump();
void reset();
void registerResetCallback(Callback *cb);
inline Temp inline Temp
operator+(Temp l, Temp r) operator+(Temp l, Temp r)
{ {
@ -2931,6 +2895,34 @@ sum(Temp val)
return NodePtr(new SumNode<std::plus<Result> >(val)); return NodePtr(new SumNode<std::plus<Result> >(val));
} }
/**
* Enable the statistics package. Before the statistics package is
* enabled, all statistics must be created and initialized and once
* the package is enabled, no more statistics can be created.
*/
void enable();
/**
* Prepare all stats for data access. This must be done before
* dumping and serialization.
*/
void prepare();
/**
* Dump all statistics data to the registered outputs
*/
void dump();
/**
* Reset all statistics to the base state
*/
void reset();
/**
* Register a callback that should be called whenever statistics are
* reset
*/
void registerResetCallback(Callback *cb);
std::list<Info *> &statsList(); std::list<Info *> &statsList();
/* namespace Stats */ } /* namespace Stats */ }

View file

@ -30,6 +30,7 @@
#include <list> #include <list>
#include "base/statistics.hh"
#include "base/stats/output.hh" #include "base/stats/output.hh"
#include "sim/eventq.hh" #include "sim/eventq.hh"
#include "sim/host.hh" #include "sim/host.hh"
@ -49,6 +50,8 @@ dump()
return; return;
lastDump = curTick; lastDump = curTick;
prepare();
list<Output *>::iterator i = OutputList.begin(); list<Output *>::iterator i = OutputList.begin();
list<Output *>::iterator end = OutputList.end(); list<Output *>::iterator end = OutputList.end();
for (; i != end; ++i) { for (; i != end; ++i) {

View file

@ -27,7 +27,14 @@
# Authors: Nathan Binkert # Authors: Nathan Binkert
import internal import internal
from internal.core import initAll, regAllStats
def setOutputDir(dir): def setOutputDir(dir):
internal.core.setOutputDir(dir) internal.core.setOutputDir(dir)
def initAll():
internal.core.initAll()
def regAllStats():
internal.core.regAllStats()

View file

@ -33,6 +33,8 @@ import sys
# import the SWIG-wrapped main C++ functions # import the SWIG-wrapped main C++ functions
import internal import internal
import core
import stats
from main import options from main import options
import SimObject import SimObject
import ticks import ticks
@ -52,23 +54,23 @@ def instantiate(root):
ini_file.close() ini_file.close()
# Initialize the global statistics # Initialize the global statistics
internal.stats.initSimStats() stats.initSimStats()
# Create the C++ sim objects and connect ports # Create the C++ sim objects and connect ports
root.createCCObject() root.createCCObject()
root.connectPorts() root.connectPorts()
# Do a second pass to finish initializing the sim objects # Do a second pass to finish initializing the sim objects
internal.core.initAll() core.initAll()
# Do a third pass to initialize statistics # Do a third pass to initialize statistics
internal.core.regAllStats() core.regAllStats()
# Check to make sure that the stats package is properly initialized # We're done registering statistics. Enable the stats package now.
internal.stats.check() stats.enable()
# Reset to put the stats in a consistent state. # Reset to put the stats in a consistent state.
internal.stats.reset() stats.reset()
def doDot(root): def doDot(root):
dot = pydot.Dot() dot = pydot.Dot()

View file

@ -28,9 +28,6 @@
import internal import internal
from internal.stats import dump
from internal.stats import initSimStats
from internal.stats import reset
from internal.stats import StatEvent as event from internal.stats import StatEvent as event
def initText(filename, desc=True, compat=True): def initText(filename, desc=True, compat=True):
@ -44,3 +41,19 @@ def initMySQL(host, database, user='', passwd='', project='test', name='test',
internal.stats.initMySQL(host, database, user, passwd, project, name, internal.stats.initMySQL(host, database, user, passwd, project, name,
sample) sample)
def initSimStats():
internal.stats.initSimStats()
def enable():
internal.stats.enable()
def dump():
# Currently prepare happens in the dump, but we should maybe move
# that out.
#internal.stats.prepare()
internal.stats.dump()
def reset():
internal.stats.reset()

View file

@ -48,7 +48,8 @@ void initMySQL(std::string host, std::string database, std::string user,
void StatEvent(bool dump, bool reset, Tick when = curTick, Tick repeat = 0); void StatEvent(bool dump, bool reset, Tick when = curTick, Tick repeat = 0);
void check(); void enable();
void prepare();
void dump(); void dump();
void reset(); void reset();