11 #include <framework/core/ProcessStatistics.h>
13 #include <framework/logging/Logger.h>
14 #include <framework/pcore/ProcHandler.h>
15 #include <framework/gearbox/Unit.h>
16 #include <framework/utilities/Utils.h>
18 #include <boost/algorithm/string/replace.hpp>
20 #include <boost/format.hpp>
28 int ProcessStatistics::getIndex(
const Module* module)
30 auto indexIt = m_modulesToStatsIndex.find(module);
31 if (indexIt == m_modulesToStatsIndex.end()) {
32 int index = m_stats.size();
33 m_modulesToStatsIndex[module] = index;
34 m_stats.emplace_back();
38 return indexIt->second;
41 void ProcessStatistics::initModule(
const Module* module)
43 int index = getIndex(module);
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)
const
59 if (!modules) modules = &(getAll());
60 int moduleNameLength = 21;
61 const int lengthOfRest = 80 - moduleNameLength;
63 int len = stats.getName().length();
64 if (len > moduleNameLength)
65 moduleNameLength = len;
67 const std::string numTabsModule = (boost::format(
"%d") % (moduleNameLength + 1)).str();
68 const std::string numWidth = (boost::format(
"%d") % (moduleNameLength + 1 + lengthOfRest)).str();
69 boost::format outputheader(
"%s %|" + numTabsModule +
"t|| %10s | %10s | %10s | %17s\n");
70 boost::format output(
"%s %|" + numTabsModule +
"t|| %10.0f | %10.0f | %10.2f | %7.2f +-%7.2f\n");
73 out << boost::format(
"%|" + numWidth +
"T=|\n");
74 out << outputheader %
"Name" %
"Calls" %
"Memory(MB)" %
"Time(s)" %
"Time(ms)/Call";
75 out << boost::format(
"%|" + numWidth +
"T=|\n");
77 std::vector<ModuleStatistics> modulesSortedByIndex(*modules);
78 sort(modulesSortedByIndex.begin(), modulesSortedByIndex.end(), [](
const ModuleStatistics & a,
const ModuleStatistics & b) { return a.getIndex() < b.getIndex(); });
83 % stats.getCalls(mode)
84 % (stats.getMemorySum(mode) / 1024)
85 % (stats.getTimeSum(mode) / Unit::s)
86 % (stats.getTimeMean(mode) / Unit::ms)
87 % (stats.getTimeStddev(mode) / Unit::ms);
90 out << boost::format(
"%|" + numWidth +
"T=|\n");
92 % (ProcHandler::isOutputProcess() ?
"Total (output proc.)" :
"Total")
98 out << boost::format(
"%|" + numWidth +
"T=|\n");
104 unsigned int minIndexUnmerged = 0;
106 B2WARNING(
"ProcessStatistics::appendUnmergedModules(): Module -> index list is empty? This might produce wrong results");
110 if (pair.second < (
int)minIndexUnmerged)
111 minIndexUnmerged = pair.second;
114 if (minIndexUnmerged > m_stats.size())
115 B2FATAL(
"(minIndexUnmerged > m_stats.size()) :( ");
116 if (minIndexUnmerged > otherObject->
m_stats.size())
117 B2FATAL(
"(minIndexUnmerged > otherObject->m_stats.size()) :( ");
121 for (
unsigned int i = 0; i < minIndexUnmerged; i++) {
125 myStats.
update(otherStats);
127 B2ERROR(
"mismatch in module names in statistics (" << myStats.
getName() <<
" vs. " << otherStats.
getName() <<
128 "). ProcessStatistics::merge() can only merge statistics that contain exactly the same modules.");
133 for (
unsigned int i = minIndexUnmerged; i < otherObject->
m_stats.size(); i++) {
135 m_stats.emplace_back(otherStats);
136 m_stats.back().setIndex(m_stats.size() - 1);
140 const int shift = m_stats.size() - otherObject->
m_stats.size();
142 B2FATAL(
"shift negative: " << shift);
145 m_modulesToStatsIndex[pair.first] = pair.second + shift;
154 if (m_stats == otherObject->m_stats) {
156 for (
unsigned int i = 0; i < otherObject->m_stats.size(); i++)
157 m_stats[i].update(otherObject->m_stats[i]);
161 m_global.update(otherObject->m_global);
163 appendUnmergedModules(otherObject);
167 if (!otherObject->m_modulesToStatsIndex.empty())
168 setTransientCounters(otherObject);
181 void ProcessStatistics::clear()
184 for (
auto& stats : m_stats) { stats.clear(); }
187 void ProcessStatistics::setCounters(
double& time,
double& memory,
188 double startTime,
double startMemory)
190 time = Utils::getClock() - startTime;
191 memory = Utils::getRssMemoryKB() - startMemory;
194 TObject* ProcessStatistics::Clone(
const char*)
const
200 std::string ProcessStatistics::getInfoHTML()
const
202 std::string s = getStatisticsString();
203 const static std::regex tagRegex(
"^==*$");
204 s = std::regex_replace(s, tagRegex,
"");
206 boost::algorithm::replace_all(s,
"|",
"</td><td>");
207 boost::algorithm::replace_all(s,
"\n",
"</td></tr><tr><td>");
208 return "Event Statistics:<br /><table border=0><tr><td>" + s +
"</td></tr></table>";