9#include <framework/core/ProcessStatistics.h>
11#include <framework/core/Environment.h>
12#include <framework/logging/Logger.h>
13#include <framework/pcore/ProcHandler.h>
14#include <framework/gearbox/Unit.h>
15#include <framework/utilities/Utils.h>
17#include <boost/algorithm/string/replace.hpp>
19#include <boost/format.hpp>
38 return indexIt->second;
45 if (module and stats.getName().empty()) {
46 const string& type =
module->getType();
47 if (type ==
"Tx" or type ==
"Rx")
50 stats.setName(module->getName());
52 stats.setIndex(index);
56 const std::vector<ModuleStatistics>* modules,
bool html)
const
60 B2WARNING(
"The calculation of the statistics wasn't enabled during processing. The requested table cannot be printed.");
63 if (!modules) modules = &(
getAll());
64 int moduleNameLength = 21;
65 const int lengthOfRest = 80 - moduleNameLength;
67 int len = stats.getName().length();
68 if (len > moduleNameLength)
69 moduleNameLength = len;
71 const std::string numTabsModule = (boost::format(
"%d") % (moduleNameLength + 1)).str();
72 const std::string numWidth = (boost::format(
"%d") % (moduleNameLength + 1 + lengthOfRest)).str();
73 boost::format outputheader(
"%s %|" + numTabsModule +
"t|| %10s | %10s | %10s | %17s\n");
74 boost::format output(
"%s %|" + numTabsModule +
"t|| %10.0f | %10.0f | %10.2f | %7.2f +-%7.2f\n");
76 outputheader = boost::format(
"<thead><tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr></thead>");
77 output = boost::format(
"<tr><td>%s</td><td>%.0f</td><td>%.0f</td><td>%.2f</td><td>%.2f ± %.2f</td></tr>");
82 out << boost::format(
"%|" + numWidth +
"T=|\n");
83 out << outputheader %
"Name" %
"Calls" %
"Memory(MB)" %
"Time(s)" %
"Time(ms)/Call";
84 out << boost::format(
"%|" + numWidth +
"T=|\n");
86 out <<
"<table border=0>";
87 out << outputheader %
"Name" %
"Calls" %
"Memory(MB)" %
"Time(s)" %
"Time(ms)/Call";
91 std::vector<ModuleStatistics> modulesSortedByIndex(*modules);
92 sort(modulesSortedByIndex.begin(), modulesSortedByIndex.end(), [](
const ModuleStatistics & a,
const ModuleStatistics & b) { return a.getIndex() < b.getIndex(); });
97 % stats.getCalls(mode)
98 % (stats.getMemorySum(mode) / 1024)
99 % (stats.getTimeSum(mode) /
Unit::s)
100 % (stats.getTimeMean(mode) /
Unit::ms)
101 % (stats.getTimeStddev(mode) /
Unit::ms);
105 out << boost::format(
"%|" + numWidth +
"T=|\n");
107 out <<
"</tbody><tfoot>";
117 out << boost::format(
"%|" + numWidth +
"T=|\n");
119 out <<
"</tfoot></table>";
126 unsigned int minIndexUnmerged = 0;
128 B2WARNING(
"ProcessStatistics::appendUnmergedModules(): Module -> index list is empty? This might produce wrong results");
132 if (pair.second < (
int)minIndexUnmerged)
133 minIndexUnmerged = pair.second;
136 if (minIndexUnmerged >
m_stats.size())
137 B2FATAL(
"(minIndexUnmerged > m_stats.size()) :( ");
138 if (minIndexUnmerged > otherObject->
m_stats.size())
139 B2FATAL(
"(minIndexUnmerged > otherObject->m_stats.size()) :( ");
143 for (
unsigned int i = 0; i < minIndexUnmerged; i++) {
147 myStats.
update(otherStats);
149 B2ERROR(
"mismatch in module names in statistics (" << myStats.
getName() <<
" vs. " << otherStats.
getName() <<
150 "). ProcessStatistics::merge() can only merge statistics that contain exactly the same modules.");
155 for (
unsigned int i = minIndexUnmerged; i < otherObject->
m_stats.size(); i++) {
157 m_stats.emplace_back(otherStats);
164 B2FATAL(
"shift negative:" <<
LogVar(
"shift", shift));
173 std::ofstream output(filename);
185 if (
m_stats == otherObject->m_stats) {
187 for (
unsigned int i = 0; i < otherObject->m_stats.size(); i++)
188 m_stats[i].update(otherObject->m_stats[i]);
192 m_global.update(otherObject->m_global);
198 if (!otherObject->m_modulesToStatsIndex.empty())
215 for (
auto& stats :
m_stats) { stats.clear(); }
219 double startTime,
double startMemory)
234 return "Event Statistics:<br />" + s;
static Environment & Instance()
Static method to get a reference to the Environment instance.
Keep track of time and memory consumption during processing.
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
const std::string & getName() const
Return the previously set name.
EStatisticCounters
Enum to define all counter types.
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
void update(const ModuleStatistics &other)
Add statistics for each category.
static bool isOutputProcess()
Return true if the process is an output process.
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.
ModuleStatistics m_global
Statistics object for global time and memory consumption.
const ModuleStatistics & getGlobal() const
Get global statistics.
const std::vector< Belle2::ModuleStatistics > & getAll() const
Get entire statistics map.
ProcessStatistics()
Constructor.
void appendUnmergedModules(const ProcessStatistics *otherObject)
Merge dissimilar objects (mainly loading ProcessStatistics from file).
double m_globalTime
store clock counter for global time consumption
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.
int getIndex(const Module *module)
get m_stats index for given module, inserting it if not found.
double m_suspendedMemory
(transient)
void initModule(const Module *module)
Init module statistics: Set name from module if still empty and remember initialization index for dis...
virtual void merge(const Mergeable *other) override
Merge other ProcessStatistics object into this one.
std::map< const Module *, int > m_modulesToStatsIndex
transient, maps Module* to m_stats index.
virtual TObject * Clone(const char *newname="") const override
Reimplement TObject::Clone() since we also need m_modulesToStatsIndex.
void write_csv(const char *filename="ProcessStatistics.csv") const
Write process statistics to a csv file.
std::string getInfoHTML() const
Return a short summary of this object's contents in HTML format.
std::vector< Belle2::ModuleStatistics > m_stats
module statistics
double m_suspendedTime
(transient)
double m_moduleTime
(transient)
virtual void clear() override
Clear collected statistics but keep names of modules.
double m_globalMemory
(transient)
double m_moduleMemory
(transient)
void setTransientCounters(const ProcessStatistics *otherObject)
Set transient counters from otherObject.
static const double ms
[millisecond]
static const double s
[second]
Class to store variables with their name which were sent to the logging service.
double getClock()
Return current value of the real-time clock.
unsigned long getRssMemoryKB()
Returns the amount of memory the process actually occupies in the physical RAM of the machine.
Abstract base class for different kinds of events.