Belle II Software  release-05-02-19
ProfileModule.cc
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2011 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Thomas Kuhr *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 #include <framework/modules/profile/ProfileModule.h>
12 #include <framework/dataobjects/ProfileInfo.h>
13 #include <framework/datastore/StoreObjPtr.h>
14 #include <framework/utilities/Utils.h>
15 #include <framework/gearbox/Unit.h>
16 
17 #include <TROOT.h>
18 #include <TCanvas.h>
19 #include <TGraph.h>
20 #include <TH1.h>
21 
22 
23 using namespace Belle2;
24 
25 //-----------------------------------------------------------------
26 // Register the Module
27 //-----------------------------------------------------------------
28 REG_MODULE(Profile)
29 
30 //-----------------------------------------------------------------
31 // Implementation
32 //-----------------------------------------------------------------
33 
34 ProfileModule::ProfileModule() : Module(), m_outputFileName(""), m_rssOutputFileName(""), m_timeOffset(Utils::getClock() / Unit::s),
35  m_nEvents(0), m_step(1),
36  m_eventInfo(k_maxPoints)
37 {
38  // Set module properties
39  setDescription("Records execution time and memory usage in ProfileInfo objects for each event. Can also graph memory usage.");
40  addParam("outputFileName", m_outputFileName, "File name of virtual memory usage plot.", std::string(""));
41  addParam("rssOutputFileName", m_rssOutputFileName, "File name of rss memory usage plot.", std::string(""));
42 }
43 
45 {
47  m_nEvents = 0;
48  m_step = 1;
49 
50  StoreObjPtr<ProfileInfo> profileInfoPtr;
51  StoreObjPtr<ProfileInfo> profileInfoStartPtr("ProfileInfo_Start", DataStore::c_Persistent);
52  StoreObjPtr<ProfileInfo> profileInfoEndPtr("ProfileInfo_End", DataStore::c_Persistent);
53  StoreObjPtr<TH1D> virtprofileHistogram("VirtualMemoryProfile", DataStore::c_Persistent);
54  StoreObjPtr<TH1D> rssProfileHistogram("RssMemoryProfile", DataStore::c_Persistent);
55  // Register the profile info objects in the data store
56  profileInfoPtr.registerInDataStore();
57  profileInfoStartPtr.registerInDataStore();
58  profileInfoEndPtr.registerInDataStore();
59  virtprofileHistogram.registerInDataStore();
60  rssProfileHistogram.registerInDataStore();
61 
62  // Store and print profile info at initialization
63  profileInfoStartPtr.create(true);
64  profileInfoStartPtr->set(m_timeOffset);
65  m_initializeInfo = MemTime(profileInfoStartPtr->getVirtualMemory(),
66  profileInfoStartPtr->getRssMemory(),
67  profileInfoStartPtr->getTimeInSec());
68  B2INFO("Virtual Memory usage at initialization [MB]: " << m_initializeInfo.virtualMem / 1024);
69 }
70 
72 {
73  // Store and print profile info at this event
74  StoreObjPtr<ProfileInfo> profileInfoPtr;
75  profileInfoPtr.create(true);
76  profileInfoPtr->set(m_timeOffset);
77  B2DEBUG(100, "Virtual Memory usage [MB]: " << profileInfoPtr->getVirtualMemory() / 1024);
78 
79  // Remember profile info at first (+burn in) and last event
80  if (m_nEvents == k_burnIn) {
81  m_startInfo = MemTime(profileInfoPtr->getVirtualMemory(),
82  profileInfoPtr->getRssMemory(),
83  profileInfoPtr->getTimeInSec());
84  }
85  m_endInfo = MemTime(profileInfoPtr->getVirtualMemory(),
86  profileInfoPtr->getRssMemory(),
87  profileInfoPtr->getTimeInSec());
88 
89  // Add profile info to the vector after each step of events
90  if (m_nEvents % m_step == 0) {
91  int index = m_nEvents / m_step;
92 
93  // Shrink the vector if the maximal number of points is reached
94  if (index >= k_maxPoints) {
95  for (int i = 1; i < k_maxPoints / 2; i++) {
96  m_eventInfo[i] = m_eventInfo[2 * i];
97  }
98  m_step *= 2;
99  index /= 2;
100  }
101 
102  m_eventInfo[index] = MemTime(profileInfoPtr->getVirtualMemory(),
103  profileInfoPtr->getRssMemory(),
104  profileInfoPtr->getTimeInSec());
105  }
106 
107  m_nEvents++;
108 }
109 
110 void ProfileModule::storeMemoryGraph(const std::string& name, const std::string& title, const std::string& yAxisName,
111  const std::string& imgOutput, const MemoryExtractLambda& lmdMemoryExtract)
112 {
113  // Create and save a plot of the memory usage vs. time
114  int nPoints = m_nEvents / m_step;
115  double factorMB = 1. / 1024;
116  if (!imgOutput.empty()) {
117  TDirectory* saveDir = gDirectory;
118  gROOT->cd();
119  auto* can = new TCanvas();
120  auto* graph = new TGraph(nPoints);
121  for (int i = 0; i < nPoints; i++) {
122  graph->SetPoint(i, m_eventInfo[i].time, lmdMemoryExtract(m_eventInfo[i]) * factorMB);
123  }
124  graph->SetMarkerStyle(kMultiply);
125  graph->Draw("ALP");
126  TH1* histo = graph->GetHistogram();
127  histo->SetTitle("");
128  histo->GetYaxis()->SetTitle(yAxisName.c_str());
129  histo->GetXaxis()->SetTitle("Time [s]");
130  can->Print(imgOutput.c_str());
131  saveDir->cd();
132  delete can;
133  delete graph;
134  }
135 
136  // Create a histogram of the memory usage vs. number of events and add it to the DataStore
137  StoreObjPtr<TH1D> profileHistogram(name, DataStore::c_Persistent);
138  profileHistogram.assign(new TH1D(name.c_str(), title.c_str(), nPoints + 1, 0 - 0.5 * m_step, m_nEvents + 0.5 * m_step), true);
139  profileHistogram->SetDirectory(nullptr);
140  profileHistogram->SetStats(false);
141  profileHistogram->GetYaxis()->SetTitle(yAxisName.c_str());
142  profileHistogram->GetXaxis()->SetTitle("Event");
143  profileHistogram->SetBinContent(1, lmdMemoryExtract(m_initializeInfo) * factorMB);
144  for (int i = 0; i < nPoints; i++) {
145  profileHistogram->SetBinContent(i + 2, lmdMemoryExtract(m_eventInfo[i]) * factorMB);
146  }
147 }
148 
150 {
151  // Store and print profile info at termination
152  StoreObjPtr<ProfileInfo> profileInfoEndPtr("ProfileInfo_End", DataStore::c_Persistent);
153  profileInfoEndPtr.create(true);
154  profileInfoEndPtr->set(m_timeOffset);
155  m_terminateInfo = MemTime(profileInfoEndPtr->getVirtualMemory(),
156  profileInfoEndPtr->getRssMemory(),
157  profileInfoEndPtr->getTimeInSec());
158  B2INFO("Virtual Memory usage at termination [MB]: " << m_terminateInfo.virtualMem / 1024);
159  B2INFO("Rss Memory usage at termination [MB] : " << m_terminateInfo.rssMem / 1024);
160 
161  if (m_nEvents > k_burnIn) {
162  B2INFO("Virtual Memory increase per event [kB] : " << ((long)m_endInfo.virtualMem - (long)m_startInfo.virtualMem) /
163  (m_nEvents - k_burnIn));
164  B2INFO("Rss Memory increase per event [kB] : " << ((long)m_endInfo.rssMem - (long)m_startInfo.rssMem) /
165  (m_nEvents - k_burnIn));
166  B2INFO("Execution time per event [ms] : " << 1000 * (m_endInfo.time - m_startInfo.time) / (m_nEvents - k_burnIn));
167  }
168 
169  // store the plots of ther memory consumption for virtual and rss memory
170  storeMemoryGraph("VirtualMemoryProfile", "Virtual Memory usage", "Virtual Memory Usage [MB]",
172  storeMemoryGraph("RssMemoryProfile", "Rss Memory usage", "Rss Memory Usage [MB]",
174 }
Belle2::ProfileModule::MemTime::time
double time
execution time
Definition: ProfileModule.h:106
Belle2::ProfileModule::MemTime::virtualMem
unsigned long virtualMem
virtual memory usage
Definition: ProfileModule.h:103
Belle2::Unit::s
static const double s
[second]
Definition: Unit.h:105
Belle2::ProfileModule::m_rssOutputFileName
std::string m_rssOutputFileName
Name for rss image output file.
Definition: ProfileModule.h:91
REG_MODULE
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:652
Belle2::ProfileModule::m_initializeInfo
MemTime m_initializeInfo
memory usage and time at initialization
Definition: ProfileModule.h:143
Belle2::ProfileModule::terminate
virtual void terminate() override
Terminate the Module.
Definition: ProfileModule.cc:149
Belle2::ProfileModule::m_endInfo
MemTime m_endInfo
memory usage and time at end of event loop
Definition: ProfileModule.h:149
Belle2::ProfileModule::m_nEvents
int m_nEvents
event counter
Definition: ProfileModule.h:145
Belle2::ProfileModule
A module that measures the execution time and memory usage per event.
Definition: ProfileModule.h:51
Belle2::Module
Base class for Modules.
Definition: Module.h:74
Belle2::ProfileModule::m_extractVirtualMem
const MemoryExtractLambda m_extractVirtualMem
Lambda expression to return the virtual memory from a MemTime data structure.
Definition: ProfileModule.h:120
Belle2::ProfileModule::MemTime
An internal struct to store pairs of memory usage and time.
Definition: ProfileModule.h:99
Belle2::ProfileModule::k_burnIn
static const int k_burnIn
number of events before the average time measurement is started
Definition: ProfileModule.h:93
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::StoreObjPtr
Type-safe access to single objects in the data store.
Definition: ParticleList.h:33
Belle2::ProfileModule::m_startInfo
MemTime m_startInfo
memory usage and time at start of event loop + burn in
Definition: ProfileModule.h:148
Belle2::ProfileModule::initialize
virtual void initialize() override
Initializes the Module.
Definition: ProfileModule.cc:44
Belle2::ProfileModule::m_outputFileName
std::string m_outputFileName
Name for image output file.
Definition: ProfileModule.h:85
Belle2::ProfileModule::m_timeOffset
double m_timeOffset
time at module creation
Definition: ProfileModule.h:142
Belle2::ProfileModule::m_step
int m_step
number of events between profile points
Definition: ProfileModule.h:146
Belle2::ProfileModule::event
virtual void event() override
Event profiling.
Definition: ProfileModule.cc:71
Belle2::DataStore::c_Persistent
@ c_Persistent
Object is available during entire execution time.
Definition: DataStore.h:62
Belle2::Utils::getClock
double getClock()
Return current value of the real-time clock.
Definition: Utils.cc:58
Belle2::ProfileModule::m_eventInfo
std::vector< MemTime > m_eventInfo
memory usage and time at individual events
Definition: ProfileModule.h:147
Belle2::ProfileModule::k_maxPoints
static const int k_maxPoints
maximal number of profile points
Definition: ProfileModule.h:94
Belle2::ProfileModule::MemTime::rssMem
unsigned long rssMem
rss memory usage
Definition: ProfileModule.h:105
Belle2::ProfileModule::m_extractRssMem
const MemoryExtractLambda m_extractRssMem
Lambda expression to return the Rss memory from a MemTime data structure.
Definition: ProfileModule.h:125
Belle2::Unit
The Unit class.
Definition: Unit.h:50
Belle2::ProfileModule::storeMemoryGraph
void storeMemoryGraph(const std::string &name, const std::string &title, const std::string &xAxisName, const std::string &imgOutput, const MemoryExtractLambda &lmdMemoryExtract)
Stores the memory usage of the application over time in plots.
Definition: ProfileModule.cc:110
Belle2::ProfileModule::MemoryExtractLambda
std::function< unsigned long(MemTime const &) > MemoryExtractLambda
Signature of the lambda functions, which are used to extract the memory usage from teh MemTime struct...
Definition: ProfileModule.h:115
Belle2::ProfileModule::m_terminateInfo
MemTime m_terminateInfo
memory usage and time at termination
Definition: ProfileModule.h:144