9 #include <framework/core/ProcessStatistics.h> 
   11 #include <framework/logging/Logger.h> 
   12 #include <framework/pcore/ProcHandler.h> 
   13 #include <framework/gearbox/Unit.h> 
   14 #include <framework/utilities/Utils.h> 
   16 #include <boost/algorithm/string/replace.hpp> 
   18 #include <boost/format.hpp> 
   26 int ProcessStatistics::getIndex(
const Module* module)
 
   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();
 
   36     return indexIt->second;
 
   39 void ProcessStatistics::initModule(
const Module* module)
 
   41   int index = getIndex(module);
 
   43   if (module and stats.getName().empty()) {
 
   44     const string& type = module->getType();
 
   45     if (type == 
"Tx" or type == 
"Rx")
 
   48       stats.setName(module->getName());
 
   50   stats.setIndex(index);
 
   54                                               const std::vector<ModuleStatistics>* modules, 
bool html)
 const 
   57   if (!modules) modules = &(getAll());
 
   58   int moduleNameLength = 21; 
 
   59   const int lengthOfRest = 80 - moduleNameLength;
 
   61     int len = stats.getName().length();
 
   62     if (len > moduleNameLength)
 
   63       moduleNameLength = len;
 
   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");
 
   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 ± %.2f</td></tr>");
 
   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");
 
   80     out << 
"<table border=0>";
 
   81     out << outputheader % 
"Name" % 
"Calls" % 
"Memory(MB)" % 
"Time(s)" % 
"Time(ms)/Call";
 
   85   std::vector<ModuleStatistics> modulesSortedByIndex(*modules);
 
   86   sort(modulesSortedByIndex.begin(), modulesSortedByIndex.end(), [](
const ModuleStatistics & a, 
const ModuleStatistics & b) { return a.getIndex() < b.getIndex(); });
 
   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);
 
   99     out << boost::format(
"%|" + numWidth + 
"T=|\n");
 
  101     out << 
"</tbody><tfoot>";
 
  104       % (ProcHandler::isOutputProcess() ? 
"Total (output proc.)" : 
"Total")
 
  111     out << boost::format(
"%|" + numWidth + 
"T=|\n");
 
  113     out << 
"</tfoot></table>";
 
  120   unsigned int minIndexUnmerged = 0;
 
  122     B2WARNING(
"ProcessStatistics::appendUnmergedModules(): Module -> index list is empty? This might produce wrong results");
 
  126       if (pair.second < (
int)minIndexUnmerged)
 
  127         minIndexUnmerged = pair.second;
 
  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()) :( ");
 
  137   for (
unsigned int i = 0; i < minIndexUnmerged; i++) {
 
  141       myStats.
update(otherStats);
 
  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.");
 
  149   for (
unsigned int i = minIndexUnmerged; i < otherObject->
m_stats.size(); i++) {
 
  151     m_stats.emplace_back(otherStats);
 
  152     m_stats.back().setIndex(m_stats.size() - 1);
 
  156   const int shift = m_stats.size() - otherObject->
m_stats.size();
 
  158     B2FATAL(
"shift negative:" << 
LogVar(
"shift", shift));
 
  161     m_modulesToStatsIndex[pair.first] = pair.second + shift;
 
  170   if (m_stats == otherObject->m_stats) {
 
  172     for (
unsigned int i = 0; i < otherObject->m_stats.size(); i++)
 
  173       m_stats[i].update(otherObject->m_stats[i]);
 
  177     m_global.update(otherObject->m_global);
 
  179     appendUnmergedModules(otherObject);
 
  183   if (!otherObject->m_modulesToStatsIndex.empty())
 
  184     setTransientCounters(otherObject);
 
  197 void ProcessStatistics::clear()
 
  200   for (
auto& stats : m_stats) { stats.clear(); }
 
  203 void ProcessStatistics::setCounters(
double& time, 
double& memory,
 
  204                                     double startTime, 
double startMemory)
 
  206   time = Utils::getClock() - startTime;
 
  207   memory = Utils::getRssMemoryKB() - startMemory;
 
  210 TObject* ProcessStatistics::Clone(
const char*)
 const 
  216 std::string ProcessStatistics::getInfoHTML()
 const 
  218   std::string s = getStatisticsString();
 
  219   return "Event Statistics:<br />" + s;
 
Abstract base class for objects that can be merged.
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.
Class to collect call statistics for all modules.
double m_globalTime
store clock counter for global time consumption
double m_suspendedMemory
(transient)
std::map< const Module *, int > m_modulesToStatsIndex
transient, maps Module* to m_stats index.
std::vector< Belle2::ModuleStatistics > m_stats
module statistics
double m_suspendedTime
(transient)
double m_moduleTime
(transient)
double m_globalMemory
(transient)
double m_moduleMemory
(transient)
Class to store variables with their name which were sent to the logging service.
Abstract base class for different kinds of events.