Belle II Software  release-08-01-10
ProfileModule.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #include <framework/modules/profile/ProfileModule.h>
10 #include <framework/core/MetadataService.h>
11 #include <framework/dataobjects/ProfileInfo.h>
12 #include <framework/datastore/StoreObjPtr.h>
13 #include <framework/utilities/Utils.h>
14 #include <framework/gearbox/Unit.h>
15 
16 #include <TROOT.h>
17 #include <TCanvas.h>
18 #include <TGraph.h>
19 #include <TH1.h>
20 
21 
22 using namespace Belle2;
23 
24 //-----------------------------------------------------------------
25 // Register the Module
26 //-----------------------------------------------------------------
27 REG_MODULE(Profile);
28 
29 //-----------------------------------------------------------------
30 // Implementation
31 //-----------------------------------------------------------------
32 
33 ProfileModule::ProfileModule() : Module(), m_outputFileName(""), m_rssOutputFileName(""), m_timeOffset(Utils::getClock() / Unit::s),
34  m_nEvents(0), m_step(1),
35  m_eventInfo(k_maxPoints)
36 {
37  // Set module properties
38  setDescription("Records execution time and memory usage in ProfileInfo objects for each event. Can also graph memory usage.");
39  addParam("outputFileName", m_outputFileName, "File name of virtual memory usage plot.", std::string(""));
40  addParam("rssOutputFileName", m_rssOutputFileName, "File name of rss memory usage plot.", std::string(""));
41 }
42 
44 {
46  m_nEvents = 0;
47  m_step = 1;
48 
49  StoreObjPtr<ProfileInfo> profileInfoPtr;
50  StoreObjPtr<ProfileInfo> profileInfoStartPtr("ProfileInfo_Start", DataStore::c_Persistent);
51  StoreObjPtr<ProfileInfo> profileInfoEndPtr("ProfileInfo_End", DataStore::c_Persistent);
52  StoreObjPtr<TH1D> virtprofileHistogram("VirtualMemoryProfile", DataStore::c_Persistent);
53  StoreObjPtr<TH1D> rssProfileHistogram("RssMemoryProfile", DataStore::c_Persistent);
54  // Register the profile info objects in the data store
55  profileInfoPtr.registerInDataStore();
56  profileInfoStartPtr.registerInDataStore();
57  profileInfoEndPtr.registerInDataStore();
58  virtprofileHistogram.registerInDataStore();
59  rssProfileHistogram.registerInDataStore();
60 
61  // Store and print profile info at initialization
62  profileInfoStartPtr.create(true);
63  profileInfoStartPtr->set(m_timeOffset);
64  m_initializeInfo = MemTime(profileInfoStartPtr->getVirtualMemory(),
65  profileInfoStartPtr->getRssMemory(),
66  profileInfoStartPtr->getTimeInSec());
67  B2INFO("Virtual Memory usage at initialization [MB]: " << m_initializeInfo.virtualMem / 1024);
68 }
69 
71 {
72  // Store and print profile info at this event
73  StoreObjPtr<ProfileInfo> profileInfoPtr;
74  profileInfoPtr.create(true);
75  profileInfoPtr->set(m_timeOffset);
76  B2DEBUG(100, "Virtual Memory usage [MB]: " << profileInfoPtr->getVirtualMemory() / 1024);
77 
78  // Remember profile info at first (+burn in) and last event
79  if (m_nEvents == k_burnIn) {
80  m_startInfo = MemTime(profileInfoPtr->getVirtualMemory(),
81  profileInfoPtr->getRssMemory(),
82  profileInfoPtr->getTimeInSec());
83  }
84  m_endInfo = MemTime(profileInfoPtr->getVirtualMemory(),
85  profileInfoPtr->getRssMemory(),
86  profileInfoPtr->getTimeInSec());
87 
88  // Add profile info to the vector after each step of events
89  if (m_nEvents % m_step == 0) {
90  int index = m_nEvents / m_step;
91 
92  // Shrink the vector if the maximal number of points is reached
93  if (index >= k_maxPoints) {
94  for (int i = 1; i < k_maxPoints / 2; i++) {
95  m_eventInfo[i] = m_eventInfo[2 * i];
96  }
97  m_step *= 2;
98  index /= 2;
99  }
100 
101  m_eventInfo[index] = MemTime(profileInfoPtr->getVirtualMemory(),
102  profileInfoPtr->getRssMemory(),
103  profileInfoPtr->getTimeInSec());
104  }
105 
106  m_nEvents++;
107 }
108 
109 void ProfileModule::storeMemoryGraph(const std::string& name, const std::string& title, const std::string& yAxisName,
110  const std::string& imgOutput, const MemoryExtractLambda& lmdMemoryExtract)
111 {
112  // Create and save a plot of the memory usage vs. time
113  int nPoints = m_nEvents / m_step;
114  double factorMB = 1. / 1024;
115  if (!imgOutput.empty()) {
116  TDirectory* saveDir = gDirectory;
117  gROOT->cd();
118  gROOT->SetBatch(true);
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 
175  // add them to the metadata service
178 
179 }
@ c_Persistent
Object is available during entire execution time.
Definition: DataStore.h:60
static MetadataService & Instance()
Static method to get a reference to the MetadataService instance.
void addRootNtupleFile(const std::string &fileName)
Add the metadata of a root ntuple file.
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
const MemoryExtractLambda m_extractVirtualMem
Lambda expression to return the virtual memory from a MemTime data structure.
MemTime m_startInfo
memory usage and time at start of event loop + burn in
static const int k_maxPoints
maximal number of profile points
Definition: ProfileModule.h:84
static const int k_burnIn
number of events before the average time measurement is started
Definition: ProfileModule.h:83
virtual void initialize() override
Initializes the Module.
MemTime m_endInfo
memory usage and time at end of event loop
virtual void event() override
Event profiling.
std::function< unsigned long(MemTime const &) > MemoryExtractLambda
Signature of the lambda functions, which are used to extract the memory usage from teh MemTime struct...
virtual void terminate() override
Terminate the Module.
int m_step
number of events between profile points
std::vector< MemTime > m_eventInfo
memory usage and time at individual events
const MemoryExtractLambda m_extractRssMem
Lambda expression to return the Rss memory from a MemTime data structure.
MemTime m_terminateInfo
memory usage and time at termination
ProfileModule()
Constructor.
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.
std::string m_rssOutputFileName
Name for rss image output file.
Definition: ProfileModule.h:81
double m_timeOffset
time at module creation
MemTime m_initializeInfo
memory usage and time at initialization
std::string m_outputFileName
Name for image output file.
Definition: ProfileModule.h:75
int m_nEvents
event counter
bool assign(TObject *object, bool replace=false)
Assign 'object' to this accessor.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
bool create(bool replace=false)
Create a default object in the data store.
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:96
The Unit class.
Definition: Unit.h:40
static const double s
[second]
Definition: Unit.h:95
REG_MODULE(arichBtest)
Register the Module.
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
double getClock()
Return current value of the real-time clock.
Definition: Utils.cc:66
Abstract base class for different kinds of events.
An internal struct to store pairs of memory usage and time.
Definition: ProfileModule.h:89
unsigned long virtualMem
virtual memory usage
Definition: ProfileModule.h:93
double time
execution time
Definition: ProfileModule.h:96
unsigned long rssMem
rss memory usage
Definition: ProfileModule.h:95