Belle II Software development
ProcessStatistics Class Reference

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

#include <ProcessStatistics.h>

Inheritance diagram for ProcessStatistics:
Mergeable

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.
 
void write_csv (const char *filename="ProcessStatistics.csv") const
 Write process statistics to a csv file.
 
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 119 of file ProcessStatistics.cc.

120{
121 unsigned int minIndexUnmerged = 0;
122 if (otherObject->m_modulesToStatsIndex.empty()) {
123 B2WARNING("ProcessStatistics::appendUnmergedModules(): Module -> index list is empty? This might produce wrong results");
124 } else {
125 minIndexUnmerged = otherObject->m_modulesToStatsIndex.begin()->second;
126 for (auto pair : otherObject->m_modulesToStatsIndex) {
127 if (pair.second < (int)minIndexUnmerged)
128 minIndexUnmerged = pair.second;
129 }
130 }
131 if (minIndexUnmerged > m_stats.size())
132 B2FATAL("(minIndexUnmerged > m_stats.size()) :( ");
133 if (minIndexUnmerged > otherObject->m_stats.size())
134 B2FATAL("(minIndexUnmerged > otherObject->m_stats.size()) :( ");
135
136
137 //the first minIndexUnmerged entries in m_stats should just be merged...
138 for (unsigned int i = 0; i < minIndexUnmerged; i++) {
139 ModuleStatistics& myStats = m_stats[i];
140 const ModuleStatistics& otherStats = otherObject->m_stats[i];
141 if (myStats.getName() == otherStats.getName()) {
142 myStats.update(otherStats);
143 } else {
144 B2ERROR("mismatch in module names in statistics (" << myStats.getName() << " vs. " << otherStats.getName() <<
145 "). ProcessStatistics::merge() can only merge statistics that contain exactly the same modules.");
146 }
147 }
148
149 //append the rest
150 for (unsigned int i = minIndexUnmerged; i < otherObject->m_stats.size(); i++) {
151 const ModuleStatistics& otherStats = otherObject->m_stats[i];
152 m_stats.emplace_back(otherStats);
153 m_stats.back().setIndex(m_stats.size() - 1);
154 }
155 //copy m_modulesToStatsIndex
156 //shift indices by #entries missing in otherObject
157 const int shift = m_stats.size() - otherObject->m_stats.size();
158 if (shift < 0) {
159 B2FATAL("shift negative:" << LogVar("shift", shift));
160 }
161 for (auto pair : otherObject->m_modulesToStatsIndex) {
162 m_modulesToStatsIndex[pair.first] = pair.second + shift;
163 }
164}
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 207 of file ProcessStatistics.cc.

208{
209 m_global.clear();
210 for (auto& stats : m_stats) { stats.clear(); }
211}
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 220 of file ProcessStatistics.cc.

221{
222 auto* p = new ProcessStatistics(*this);
223 return p;
224}

◆ 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 27 of file ProcessStatistics.cc.

28{
29 auto indexIt = m_modulesToStatsIndex.find(module);
30 if (indexIt == m_modulesToStatsIndex.end()) {
31 int index = m_stats.size();
32 m_modulesToStatsIndex[module] = index;
33 m_stats.emplace_back();
34 initModule(module);
35 return index;
36 } else {
37 return indexIt->second;
38 }
39}
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 226 of file ProcessStatistics.cc.

227{
228 std::string s = getStatisticsString();
229 return "Event Statistics:<br />" + s;
230}
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 54 of file ProcessStatistics.cc.

56{
57 const ModuleStatistics& global = getGlobal();
58 if (!modules) modules = &(getAll());
59 int moduleNameLength = 21; //minimum: 80 characters
60 const int lengthOfRest = 80 - moduleNameLength;
61 for (const ModuleStatistics& stats : *modules) {
62 int len = stats.getName().length();
63 if (len > moduleNameLength)
64 moduleNameLength = len;
65 }
66 const std::string numTabsModule = (boost::format("%d") % (moduleNameLength + 1)).str();
67 const std::string numWidth = (boost::format("%d") % (moduleNameLength + 1 + lengthOfRest)).str();
68 boost::format outputheader("%s %|" + numTabsModule + "t|| %10s | %10s | %10s | %17s\n");
69 boost::format output("%s %|" + numTabsModule + "t|| %10.0f | %10.0f | %10.2f | %7.2f +-%7.2f\n");
70 if (html) {
71 outputheader = boost::format("<thead><tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr></thead>");
72 output = boost::format("<tr><td>%s</td><td>%.0f</td><td>%.0f</td><td>%.2f</td><td>%.2f &plusmn; %.2f</td></tr>");
73 }
74
75 stringstream out;
76 if (!html) {
77 out << boost::format("%|" + numWidth + "T=|\n");
78 out << outputheader % "Name" % "Calls" % "Memory(MB)" % "Time(s)" % "Time(ms)/Call";
79 out << boost::format("%|" + numWidth + "T=|\n");
80 } else {
81 out << "<table border=0>";
82 out << outputheader % "Name" % "Calls" % "Memory(MB)" % "Time(s)" % "Time(ms)/Call";
83 out << "<tbody>";
84 }
85
86 std::vector<ModuleStatistics> modulesSortedByIndex(*modules);
87 sort(modulesSortedByIndex.begin(), modulesSortedByIndex.end(), [](const ModuleStatistics & a, const ModuleStatistics & b) { return a.getIndex() < b.getIndex(); });
88
89 for (const ModuleStatistics& stats : modulesSortedByIndex) {
90 out << output
91 % stats.getName()
92 % stats.getCalls(mode)
93 % (stats.getMemorySum(mode) / 1024)
94 % (stats.getTimeSum(mode) / Unit::s)
95 % (stats.getTimeMean(mode) / Unit::ms)
96 % (stats.getTimeStddev(mode) / Unit::ms);
97 }
98
99 if (!html) {
100 out << boost::format("%|" + numWidth + "T=|\n");
101 } else {
102 out << "</tbody><tfoot>";
103 }
104 out << output
105 % (ProcHandler::isOutputProcess() ? "Total (output proc.)" : "Total")
106 % global.getCalls(mode)
107 % (global.getMemorySum(mode) / 1024)
108 % (global.getTimeSum(mode) / Unit::s)
109 % (global.getTimeMean(mode) / Unit::ms)
110 % (global.getTimeStddev(mode) / Unit::ms);
111 if (!html) {
112 out << boost::format("%|" + numWidth + "T=|\n");
113 } else {
114 out << "</tfoot></table>";
115 }
116 return out.str();
117}
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 40 of file ProcessStatistics.cc.

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

◆ merge()

void merge ( const Mergeable other)
overridevirtual

Merge other ProcessStatistics object into this one.

Implements Mergeable.

Definition at line 176 of file ProcessStatistics.cc.

177{
178 const auto* otherObject = static_cast<const ProcessStatistics*>(other);
179
180 if (m_stats == otherObject->m_stats) {
181 //fast version for merging between processes
182 for (unsigned int i = 0; i < otherObject->m_stats.size(); i++)
183 m_stats[i].update(otherObject->m_stats[i]);
184 } else {
185 //note: statistics in m_global are not merged for pp, we use the output process instead
186 //for objects read from file we need to add them though
187 m_global.update(otherObject->m_global);
188
189 appendUnmergedModules(otherObject);
190 }
191
192 //if the other object has transient data on modules, copy remaining counters
193 if (!otherObject->m_modulesToStatsIndex.empty())
194 setTransientCounters(otherObject);
195}
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 213 of file ProcessStatistics.cc.

215{
216 time = Utils::getClock() - startTime;
217 memory = Utils::getRssMemoryKB() - startMemory;
218}
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 197 of file ProcessStatistics.cc.

198{
199 m_globalTime = otherObject->m_globalTime;
200 m_globalMemory = otherObject->m_globalMemory;
201 m_moduleTime = otherObject->m_moduleTime;
202 m_moduleMemory = otherObject->m_moduleMemory;
203 m_suspendedTime = otherObject->m_suspendedTime;
205}

◆ 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.

◆ write_csv()

void write_csv ( const char *  filename = "ProcessStatistics.csv") const

Write process statistics to a csv file.

Definition at line 166 of file ProcessStatistics.cc.

167{
168 std::ofstream output(filename);
169 m_global.csv_header(output);
170 for (auto stats : m_stats) {
171 stats.csv(output);
172 }
173 m_global.csv(output);
174}
void csv(std::ostream &output) const
write data to the given stream in csv format
void csv_header(std::ostream &output) const
write csv header to the given stream

Member Data Documentation

◆ m_global

ModuleStatistics m_global
private

Statistics object for global time and memory consumption.

Definition at line 208 of file ProcessStatistics.h.

◆ m_globalMemory

double m_globalMemory
private

(transient)

store heap size for global memory consumption in KB

Definition at line 219 of file ProcessStatistics.h.

◆ m_globalTime

double m_globalTime
private

store clock counter for global time consumption

Definition at line 217 of file ProcessStatistics.h.

◆ m_moduleMemory

double m_moduleMemory
private

(transient)

store heap size for memory consumption by modules

Definition at line 223 of file ProcessStatistics.h.

◆ m_modulesToStatsIndex

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

transient, maps Module* to m_stats index.

Definition at line 212 of file ProcessStatistics.h.

◆ m_moduleTime

double m_moduleTime
private

(transient)

store clock counter for time consumption by modules

Definition at line 221 of file ProcessStatistics.h.

◆ m_stats

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

module statistics

Definition at line 209 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 231 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 227 of file ProcessStatistics.h.


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