Belle II Software development
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
22using namespace Belle2;
23
24//-----------------------------------------------------------------
25// Register the Module
26//-----------------------------------------------------------------
27REG_MODULE(Profile);
28
29//-----------------------------------------------------------------
30// Implementation
31//-----------------------------------------------------------------
32
33ProfileModule::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
109void 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
void addNtuple(const std::string &fileName)
Add the metadata of any ntuple file.
static MetadataService & Instance()
Static method to get a reference to the MetadataService instance.
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
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
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
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:94
double time
execution time
Definition: ProfileModule.h:96
unsigned long rssMem
rss memory usage
Definition: ProfileModule.h:95