Belle II Software light-2406-ragdoll
ProcessStatistics Class Reference

Class to collect call statistics for all modules. More...

#include <ProcessStatistics.h>

Inheritance diagram for ProcessStatistics:
Collaboration diagram for ProcessStatistics:

Public Member Functions

 ProcessStatistics ()
 Constructor.
 
std::string getStatisticsString (ModuleStatistics::EStatisticCounters type=ModuleStatistics::c_Event, const std::vector< Belle2::ModuleStatistics > *modules=nullptr, bool html=false) const
 Return string with statistics for all modules.
 
const ModuleStatisticsgetGlobal () const
 Get global statistics.
 
const std::vector< Belle2::ModuleStatistics > & getAll () const
 Get entire statistics map.
 
void startGlobal ()
 Start timer for global measurement.
 
void suspendGlobal ()
 Suspend timer for global measurement, needed for newRun.
 
void resumeGlobal ()
 Resume timer after call to suspendGlobal()
 
void stopGlobal (ModuleStatistics::EStatisticCounters type)
 Stop global timer and add values to the statistic counter.
 
void startModule ()
 Start module timer.
 
void stopModule (const Module *module, ModuleStatistics::EStatisticCounters type)
 Stop module counter and attribute values to appropriate module.
 
void initModule (const Module *module)
 Init module statistics: Set name from module if still empty and remember initialization index for display.
 
ModuleStatisticsgetStatistics (const Module *module)
 Get statistics for single module.
 
int getIndex (const Module *module)
 get m_stats index for given module, inserting it if not found.
 
virtual void merge (const Mergeable *other) override
 Merge other ProcessStatistics object into this one.
 
virtual void clear () override
 Clear collected statistics but keep names of modules.
 
virtual TObject * Clone (const char *newname="") const override
 Reimplement TObject::Clone() since we also need m_modulesToStatsIndex.
 
std::string getInfoHTML () const
 Return a short summary of this object's contents in HTML format.
 
virtual void removeSideEffects ()
 An ugly little method that is called before event() for input and worker processes.
 
virtual Long64_t Merge (TCollection *hlist)
 Allow merging using TFileMerger if saved directly to a file.
 
virtual void Reset ()
 Root-like Reset function for "template compatibility" with ROOT objects.
 
virtual void SetDirectory (TDirectory *)
 Root-like SetDirectory function for "template compatibility" with ROOT objects.
 

Private Member Functions

 ProcessStatistics (const ProcessStatistics &)=default
 Hide copy constructor.
 
ProcessStatisticsoperator= (ProcessStatistics &)
 Prohibit assignment operator.
 
void appendUnmergedModules (const ProcessStatistics *otherObject)
 Merge dissimilar objects (mainly loading ProcessStatistics from file).
 
void setTransientCounters (const ProcessStatistics *otherObject)
 Set transient counters from otherObject.
 
void setCounters (double &time, double &memory, double startTime=0, double startMemory=0)
 Set counters time and memory to contain the current clock value and memory consumption respectively.
 
 ClassDefOverride (ProcessStatistics, 2)
 (transient)
 
 ClassDef (Mergeable, 0)
 Abstract base class for objects that can be merged.
 

Private Attributes

ModuleStatistics m_global
 Statistics object for global time and memory consumption.
 
std::vector< Belle2::ModuleStatisticsm_stats
 module statistics
 
std::map< const Module *, int > m_modulesToStatsIndex
 transient, maps Module* to m_stats index.
 
double m_globalTime
 store clock counter for global time consumption
 
double m_globalMemory
 (transient)
 
double m_moduleTime
 (transient)
 
double m_moduleMemory
 (transient)
 
double m_suspendedTime
 (transient)
 
double m_suspendedMemory
 (transient)
 

Detailed Description

Class to collect call statistics for all modules.

This class is used to collect call and time statistics for all modules. It is implemented as a singleton and will keep track of the number of times a module will be called and the time the module spends in these calls.

Altough this class can be used in C++, its main purpose is to be used in python. In the python environment it is reachable through the "statistics" object in the pybasf2 module. Most simple use is to just print the event statistics after the process loop:

‍process(...) print(statistics)

Different types of statistics can be printed using

‍print(statistics(type))

where type can be one of

  • statistics.INIT -> time/calls spent in initialize()
  • statistics.BEGIN_RUN -> time/calls spent in beginRun()
  • statistics.EVENT -> time/calls spent in event()
  • statistics.END_RUN -> time/calls spent in endRun()
  • statistics.TERM -> time/calls spent in terminate()
  • statistics.TOTAL -> sum of all the above

It is also possible to restrict the event statistics to a list of modules one is interested in

‍foo = register_module("Foo") bar = register_module("Bar")

...

‍process(...) print(statistics([foo,bar])) print(statistics([foo,bar],statistics.BEGIN_RUN))

More detailed statistics can be reached by accessing the statistics for all modules directly:

‍process(...) for stats in statistics.modules: print(stats.name, stats.time(statistics.EVENT), stats.calls(statistics.BEGIN_RUN))

Available attributes/methods for the statistics objects are

  • name: name of the module
  • time(type=statistics.EVENT): time in seconds spent in function
  • calls(type=statistics.EVENT): number of calls to function

The global statistics for the framework can be accessed via statistics.framework

The name shown in the statistics can be modified. This is particular useful if there is more than one instance of a given module in the path

‍foo = register_module("Foo") statistics.set_name(foo,"Footastic")

Definition at line 84 of file ProcessStatistics.h.

Constructor & Destructor Documentation

◆ ProcessStatistics()

ProcessStatistics ( )
inline

Constructor.

Definition at line 87 of file ProcessStatistics.h.

87 :
ModuleStatistics m_global
Statistics object for global time and memory consumption.
double m_globalTime
store clock counter for global time consumption
double m_suspendedMemory
(transient)
double m_suspendedTime
(transient)
double m_moduleTime
(transient)
double m_globalMemory
(transient)
double m_moduleMemory
(transient)

Member Function Documentation

◆ appendUnmergedModules()

void appendUnmergedModules ( const ProcessStatistics otherObject)
private

Merge dissimilar objects (mainly loading ProcessStatistics from file).

Definition at line 118 of file ProcessStatistics.cc.

119{
120 unsigned int minIndexUnmerged = 0;
121 if (otherObject->m_modulesToStatsIndex.empty()) {
122 B2WARNING("ProcessStatistics::appendUnmergedModules(): Module -> index list is empty? This might produce wrong results");
123 } else {
124 minIndexUnmerged = otherObject->m_modulesToStatsIndex.begin()->second;
125 for (auto pair : otherObject->m_modulesToStatsIndex) {
126 if (pair.second < (int)minIndexUnmerged)
127 minIndexUnmerged = pair.second;
128 }
129 }
130 if (minIndexUnmerged > m_stats.size())
131 B2FATAL("(minIndexUnmerged > m_stats.size()) :( ");
132 if (minIndexUnmerged > otherObject->m_stats.size())
133 B2FATAL("(minIndexUnmerged > otherObject->m_stats.size()) :( ");
134
135
136 //the first minIndexUnmerged entries in m_stats should just be merged...
137 for (unsigned int i = 0; i < minIndexUnmerged; i++) {
138 ModuleStatistics& myStats = m_stats[i];
139 const ModuleStatistics& otherStats = otherObject->m_stats[i];
140 if (myStats.getName() == otherStats.getName()) {
141 myStats.update(otherStats);
142 } else {
143 B2ERROR("mismatch in module names in statistics (" << myStats.getName() << " vs. " << otherStats.getName() <<
144 "). ProcessStatistics::merge() can only merge statistics that contain exactly the same modules.");
145 }
146 }
147
148 //append the rest
149 for (unsigned int i = minIndexUnmerged; i < otherObject->m_stats.size(); i++) {
150 const ModuleStatistics& otherStats = otherObject->m_stats[i];
151 m_stats.emplace_back(otherStats);
152 m_stats.back().setIndex(m_stats.size() - 1);
153 }
154 //copy m_modulesToStatsIndex
155 //shift indices by #entries missing in otherObject
156 const int shift = m_stats.size() - otherObject->m_stats.size();
157 if (shift < 0) {
158 B2FATAL("shift negative:" << LogVar("shift", shift));
159 }
160 for (auto pair : otherObject->m_modulesToStatsIndex) {
161 m_modulesToStatsIndex[pair.first] = pair.second + shift;
162 }
163}
Keep track of time and memory consumption during processing.
const std::string & getName() const
Return the previously set name.
void update(const ModuleStatistics &other)
Add statistics for each category.
std::map< const Module *, int > m_modulesToStatsIndex
transient, maps Module* to m_stats index.
std::vector< Belle2::ModuleStatistics > m_stats
module statistics
Class to store variables with their name which were sent to the logging service.

◆ ClassDefOverride()

ClassDefOverride ( ProcessStatistics  ,
 
)
private

(transient)

Class to collect call statistics for all modules.

◆ clear()

void clear ( )
overridevirtual

Clear collected statistics but keep names of modules.

Implements Mergeable.

Definition at line 197 of file ProcessStatistics.cc.

198{
199 m_global.clear();
200 for (auto& stats : m_stats) { stats.clear(); }
201}
void clear()
Clear all statistics.

◆ Clone()

TObject * Clone ( const char *  newname = "") const
overridevirtual

Reimplement TObject::Clone() since we also need m_modulesToStatsIndex.

Definition at line 210 of file ProcessStatistics.cc.

211{
212 auto* p = new ProcessStatistics(*this);
213 return p;
214}

◆ getAll()

const std::vector< Belle2::ModuleStatistics > & getAll ( ) const
inline

Get entire statistics map.

Definition at line 108 of file ProcessStatistics.h.

108{ return m_stats; }

◆ getGlobal()

const ModuleStatistics & getGlobal ( ) const
inline

Get global statistics.

Definition at line 105 of file ProcessStatistics.h.

105{ return m_global; }

◆ getIndex()

int getIndex ( const Module module)

get m_stats index for given module, inserting it if not found.

Definition at line 26 of file ProcessStatistics.cc.

27{
28 auto indexIt = m_modulesToStatsIndex.find(module);
29 if (indexIt == m_modulesToStatsIndex.end()) {
30 int index = m_stats.size();
31 m_modulesToStatsIndex[module] = index;
32 m_stats.emplace_back();
33 initModule(module);
34 return index;
35 } else {
36 return indexIt->second;
37 }
38}
void initModule(const Module *module)
Init module statistics: Set name from module if still empty and remember initialization index for dis...

◆ getInfoHTML()

std::string getInfoHTML ( ) const

Return a short summary of this object's contents in HTML format.

Definition at line 216 of file ProcessStatistics.cc.

217{
218 std::string s = getStatisticsString();
219 return "Event Statistics:<br />" + s;
220}
std::string getStatisticsString(ModuleStatistics::EStatisticCounters type=ModuleStatistics::c_Event, const std::vector< Belle2::ModuleStatistics > *modules=nullptr, bool html=false) const
Return string with statistics for all modules.

◆ getStatistics()

ModuleStatistics & getStatistics ( const Module module)
inline

Get statistics for single module.

Parameters
moduleShared pointer to the Module for which the statistics should be obtained

Definition at line 163 of file ProcessStatistics.h.

164 {
165 return m_stats[getIndex(module)];
166 }
int getIndex(const Module *module)
get m_stats index for given module, inserting it if not found.

◆ getStatisticsString()

string getStatisticsString ( ModuleStatistics::EStatisticCounters  type = ModuleStatistics::c_Event,
const std::vector< Belle2::ModuleStatistics > *  modules = nullptr,
bool  html = false 
) const

Return string with statistics for all modules.

Can be used in steering file with 'print(statistics)'.

Parameters
typecounter type to use for statistics
modulesmap of modules to use. If NULL, default map will be used
htmlif true return the output as html table instead of an ascii table

Definition at line 53 of file ProcessStatistics.cc.

55{
56 const ModuleStatistics& global = getGlobal();
57 if (!modules) modules = &(getAll());
58 int moduleNameLength = 21; //minimum: 80 characters
59 const int lengthOfRest = 80 - moduleNameLength;
60 for (const ModuleStatistics& stats : *modules) {
61 int len = stats.getName().length();
62 if (len > moduleNameLength)
63 moduleNameLength = len;
64 }
65 const std::string numTabsModule = (boost::format("%d") % (moduleNameLength + 1)).str();
66 const std::string numWidth = (boost::format("%d") % (moduleNameLength + 1 + lengthOfRest)).str();
67 boost::format outputheader("%s %|" + numTabsModule + "t|| %10s | %10s | %10s | %17s\n");
68 boost::format output("%s %|" + numTabsModule + "t|| %10.0f | %10.0f | %10.2f | %7.2f +-%7.2f\n");
69 if (html) {
70 outputheader = boost::format("<thead><tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr></thead>");
71 output = boost::format("<tr><td>%s</td><td>%.0f</td><td>%.0f</td><td>%.2f</td><td>%.2f &plusmn; %.2f</td></tr>");
72 }
73
74 stringstream out;
75 if (!html) {
76 out << boost::format("%|" + numWidth + "T=|\n");
77 out << outputheader % "Name" % "Calls" % "Memory(MB)" % "Time(s)" % "Time(ms)/Call";
78 out << boost::format("%|" + numWidth + "T=|\n");
79 } else {
80 out << "<table border=0>";
81 out << outputheader % "Name" % "Calls" % "Memory(MB)" % "Time(s)" % "Time(ms)/Call";
82 out << "<tbody>";
83 }
84
85 std::vector<ModuleStatistics> modulesSortedByIndex(*modules);
86 sort(modulesSortedByIndex.begin(), modulesSortedByIndex.end(), [](const ModuleStatistics & a, const ModuleStatistics & b) { return a.getIndex() < b.getIndex(); });
87
88 for (const ModuleStatistics& stats : modulesSortedByIndex) {
89 out << output
90 % stats.getName()
91 % stats.getCalls(mode)
92 % (stats.getMemorySum(mode) / 1024)
93 % (stats.getTimeSum(mode) / Unit::s)
94 % (stats.getTimeMean(mode) / Unit::ms)
95 % (stats.getTimeStddev(mode) / Unit::ms);
96 }
97
98 if (!html) {
99 out << boost::format("%|" + numWidth + "T=|\n");
100 } else {
101 out << "</tbody><tfoot>";
102 }
103 out << output
104 % (ProcHandler::isOutputProcess() ? "Total (output proc.)" : "Total")
105 % global.getCalls(mode)
106 % (global.getMemorySum(mode) / 1024)
107 % (global.getTimeSum(mode) / Unit::s)
108 % (global.getTimeMean(mode) / Unit::ms)
109 % (global.getTimeStddev(mode) / Unit::ms);
110 if (!html) {
111 out << boost::format("%|" + numWidth + "T=|\n");
112 } else {
113 out << "</tfoot></table>";
114 }
115 return out.str();
116}
value_type getTimeStddev(EStatisticCounters type=c_Total) const
return the stddev of the execution times for a given counter
value_type getCalls(EStatisticCounters type=c_Total) const
return the number of calls for a given counter type
value_type getMemorySum(EStatisticCounters type=c_Total) const
return the total used memory for a given counter
value_type getTimeSum(EStatisticCounters type=c_Total) const
return the sum of all execution times for a given counter
value_type getTimeMean(EStatisticCounters type=c_Total) const
return the mean execution time for a given counter
static bool isOutputProcess()
Return true if the process is an output process.
Definition: ProcHandler.cc:232
const ModuleStatistics & getGlobal() const
Get global statistics.
const std::vector< Belle2::ModuleStatistics > & getAll() const
Get entire statistics map.
static const double ms
[millisecond]
Definition: Unit.h:96
static const double s
[second]
Definition: Unit.h:95

◆ initModule()

void initModule ( const Module module)

Init module statistics: Set name from module if still empty and remember initialization index for display.

Definition at line 39 of file ProcessStatistics.cc.

40{
41 int index = getIndex(module);
42 ModuleStatistics& stats = m_stats.at(index);
43 if (module and stats.getName().empty()) {
44 const string& type = module->getType();
45 if (type == "Tx" or type == "Rx")
46 stats.setName(type);
47 else
48 stats.setName(module->getName());
49 }
50 stats.setIndex(index);
51}

◆ merge()

void merge ( const Mergeable other)
overridevirtual

Merge other ProcessStatistics object into this one.

Implements Mergeable.

Definition at line 166 of file ProcessStatistics.cc.

167{
168 const auto* otherObject = static_cast<const ProcessStatistics*>(other);
169
170 if (m_stats == otherObject->m_stats) {
171 //fast version for merging between processes
172 for (unsigned int i = 0; i < otherObject->m_stats.size(); i++)
173 m_stats[i].update(otherObject->m_stats[i]);
174 } else {
175 //note: statistics in m_global are not merged for pp, we use the output process instead
176 //for objects read from file we need to add them though
177 m_global.update(otherObject->m_global);
178
179 appendUnmergedModules(otherObject);
180 }
181
182 //if the other object has transient data on modules, copy remaining counters
183 if (!otherObject->m_modulesToStatsIndex.empty())
184 setTransientCounters(otherObject);
185}
Class to collect call statistics for all modules.
void appendUnmergedModules(const ProcessStatistics *otherObject)
Merge dissimilar objects (mainly loading ProcessStatistics from file).
void setTransientCounters(const ProcessStatistics *otherObject)
Set transient counters from otherObject.

◆ Merge()

Long64_t Merge ( TCollection *  hlist)
virtualinherited

Allow merging using TFileMerger if saved directly to a file.

Note
dictionaries containing your Mergeable class need to be loaded, so 'hadd' will not work currently.

Definition at line 14 of file Mergeable.cc.

15{
16 Long64_t nMerged = 0;
17 if (hlist) {
18 const Mergeable* xh = nullptr;
19 TIter nxh(hlist);
20 while ((xh = dynamic_cast<Mergeable*>(nxh()))) {
21 // Add xh to me
22 merge(xh);
23 ++nMerged;
24 }
25 }
26 return nMerged;
27}
Abstract base class for objects that can be merged.
Definition: Mergeable.h:31
virtual void merge(const Mergeable *other)=0
Merge object 'other' into this one.

◆ removeSideEffects()

virtual void removeSideEffects ( )
inlinevirtualinherited

An ugly little method that is called before event() for input and worker processes.

Main use case is to detach any attached TFile from this object. In the output process, it can stay attached (and grow as much as it likes).

Reimplemented in RootMergeable< T >.

Definition at line 58 of file Mergeable.h.

58{}

◆ Reset()

virtual void Reset ( )
inlinevirtualinherited

Root-like Reset function for "template compatibility" with ROOT objects.

Alias for clear().

Definition at line 66 of file Mergeable.h.

66{clear();}
virtual void clear()=0
Clear content of this object (e.g.

◆ resumeGlobal()

void resumeGlobal ( )
inline

Resume timer after call to suspendGlobal()

Definition at line 123 of file ProcessStatistics.h.

124 {
127 }
void setCounters(double &time, double &memory, double startTime=0, double startMemory=0)
Set counters time and memory to contain the current clock value and memory consumption respectively.

◆ setCounters()

void setCounters ( double &  time,
double &  memory,
double  startTime = 0,
double  startMemory = 0 
)
private

Set counters time and memory to contain the current clock value and memory consumption respectively.

Parameters
timevariable to store clock counter
memoryvariable to store heap size
startTimevalue to subtract from clock counter
startMemoryvalue to subtract from heap size

Definition at line 203 of file ProcessStatistics.cc.

205{
206 time = Utils::getClock() - startTime;
207 memory = Utils::getRssMemoryKB() - startMemory;
208}
double getClock()
Return current value of the real-time clock.
Definition: Utils.cc:66
unsigned long getRssMemoryKB()
Returns the amount of memory the process actually occupies in the physical RAM of the machine.
Definition: Utils.cc:84

◆ SetDirectory()

virtual void SetDirectory ( TDirectory *  )
inlinevirtualinherited

Root-like SetDirectory function for "template compatibility" with ROOT objects.

Does nothing.

Definition at line 68 of file Mergeable.h.

68{}

◆ setTransientCounters()

void setTransientCounters ( const ProcessStatistics otherObject)
private

Set transient counters from otherObject.

Needed since we swap objects inside input modules.

Definition at line 187 of file ProcessStatistics.cc.

188{
189 m_globalTime = otherObject->m_globalTime;
190 m_globalMemory = otherObject->m_globalMemory;
191 m_moduleTime = otherObject->m_moduleTime;
192 m_moduleMemory = otherObject->m_moduleMemory;
193 m_suspendedTime = otherObject->m_suspendedTime;
195}

◆ startGlobal()

void startGlobal ( )
inline

Start timer for global measurement.

Definition at line 111 of file ProcessStatistics.h.

◆ startModule()

void startModule ( )
inline

Start module timer.

Definition at line 138 of file ProcessStatistics.h.

◆ stopGlobal()

void stopGlobal ( ModuleStatistics::EStatisticCounters  type)
inline

Stop global timer and add values to the statistic counter.

Definition at line 130 of file ProcessStatistics.h.

131 {
135 }
void add(EStatisticCounters type, value_type time, value_type memory)
Add a time and memory measurment to the counter of a given type.

◆ stopModule()

void stopModule ( const Module module,
ModuleStatistics::EStatisticCounters  type 
)
inline

Stop module counter and attribute values to appropriate module.

Definition at line 144 of file ProcessStatistics.h.

145 {
148 if (module && module->hasProperties(Module::c_DontCollectStatistics)) return;
149 m_stats[getIndex(module)].add(type, m_moduleTime, m_moduleMemory);
150 }
@ c_DontCollectStatistics
No statistics is collected for this module.
Definition: Module.h:84

◆ suspendGlobal()

void suspendGlobal ( )
inline

Suspend timer for global measurement, needed for newRun.

resumeGlobal should be called once endRun/newRun handling is finished

Definition at line 116 of file ProcessStatistics.h.

Member Data Documentation

◆ m_global

ModuleStatistics m_global
private

Statistics object for global time and memory consumption.

Definition at line 205 of file ProcessStatistics.h.

◆ m_globalMemory

double m_globalMemory
private

(transient)

store heap size for global memory consumption in KB

Definition at line 216 of file ProcessStatistics.h.

◆ m_globalTime

double m_globalTime
private

store clock counter for global time consumption

Definition at line 214 of file ProcessStatistics.h.

◆ m_moduleMemory

double m_moduleMemory
private

(transient)

store heap size for memory consumption by modules

Definition at line 220 of file ProcessStatistics.h.

◆ m_modulesToStatsIndex

std::map<const Module*, int> m_modulesToStatsIndex
private

transient, maps Module* to m_stats index.

Definition at line 209 of file ProcessStatistics.h.

◆ m_moduleTime

double m_moduleTime
private

(transient)

store clock counter for time consumption by modules

Definition at line 218 of file ProcessStatistics.h.

◆ m_stats

std::vector<Belle2::ModuleStatistics> m_stats
private

module statistics

Definition at line 206 of file ProcessStatistics.h.

◆ m_suspendedMemory

double m_suspendedMemory
private

(transient)

store heap size for suspended measurement. Generally this would be a stack of values but we know that we need at most one element so we keep it a plain double.

Definition at line 228 of file ProcessStatistics.h.

◆ m_suspendedTime

double m_suspendedTime
private

(transient)

store clock counter for suspended measurement. Generally this would be a stack of values but we know that we need at most one element so we keep it a plain double.

Definition at line 224 of file ProcessStatistics.h.


The documentation for this class was generated from the following files: