ATLAS Offline Software
Loading...
Searching...
No Matches
PerfStats.cxx File Reference
#include <TTree.h>
#include <TFile.h>
#include <TTimeStamp.h>
#include "xAODCore/tools/PerfStats.h"
#include "xAODCore/tools/Utils.h"
#include "xAODCore/tools/IOStats.h"
#include "xAODCore/tools/ReadStats.h"
Include dependency graph for PerfStats.cxx:

Go to the source code of this file.

Macros

#define FWD_CALL(CALL)

Functions

 ClassImp (xAOD::PerfStats) namespace xAOD

Macro Definition Documentation

◆ FWD_CALL

#define FWD_CALL ( CALL)
Value:
void PerfStats::CALL( TBranch *b, size_t basketNumber ) { \
if( m_otherPerfStats ) m_otherPerfStats->CALL( b, basketNumber ); \
} \
void PerfStats::CALL( size_t bi, size_t basketNumber ) { \
if( m_otherPerfStats ) m_otherPerfStats->CALL( bi, basketNumber ); \
} struct dummyforsemi

Function Documentation

◆ ClassImp()

ClassImp ( xAOD::PerfStats )

The destructor is a quite important function in this class. it makes sure that the static s_instance variable gets reset, and that all TVirtualPerfStats objects really get deleted.

Everywhere in the code this function should be used to access the one and only PerfStats object in memory.

Returns
A pointer to the PerfStats singleton

The user is supposed to call this function after the initialization of his/her analysis code finished, but before the event processing starts.

Parameters
clearClear the statistics gathered so far

The user is supposed to call this function once his/her analysis code finished with the event processing.

This function does most of the work of the class. It is called every time ROOT does a file I/O operation. The function takes care of registering this operation in its statistics, and checks if a new file was opened since the last I/O operation.

Parameters
fileThe file object that was read from
lenThe number of bytes that were read from the file
startThe time when the read operation started

This function is called by ROOT when it needs to unzip some data from a given inpout file.

Parameters
fileThe file the information was read from
posPosition inside the input file? (Not used.)
startThe time when the unzipping operation started
complenNot sure. (Not used.)
objlenNot sure. (Not used.)

In single process running this function is basically never called. It's only active when running on PROOF, in which case we should not care about the values given to it, but just forward it to TPerfStats. The actual amount of data read for xAOD monitoring is coming in through the FileReadEvent(...) function...

Parameters
numNumber of bytes read in "some operation"

This function is not called with anything meaningful in standalone ROOT analyses, so it just forwards the call to a possible other TVirtualPerfStats object.

Parameters
numNumber of processed events

The function just gets the number of events from the other TVirtualPerfStats object if it exists, otherwise it just returns zero.

Returns
The number of processed events

The constructor needs to do a few things. If there is already another TVirtualPerfStats object defined under gPerfStats, then it stores that pointer in order to be able to forward monitoring information to that object later on. It then overwrites gPerfStats to point to this object.

Note that this is a private function in TVirtualPerfStats, so it is not forwarded to m_otherPerfStats.

Definition at line 16 of file PerfStats.cxx.

18 {
19
20 // Initialize the static variable(s):
21 PerfStats* PerfStats::s_instance = nullptr;
22 std::mutex PerfStats::s_mutex;
23
28 PerfStats::~PerfStats() {
29
30 lock_t lock (s_mutex);
31 // Since this object can only be deleted by deleting the global
32 // gPerfStats object, make sure that all the objects get deleted
33 // if the user asked for it...
34 s_instance = nullptr;
35 if( m_otherPerfStats ) {
36 delete m_otherPerfStats;
37 }
38 }
39
45 PerfStats& PerfStats::instance() {
46
47 lock_t lock (s_mutex);
48 // Construct the object if it is now available at the moment:
49 if( ! s_instance ) {
50 s_instance = new PerfStats();
51 }
52
53 return *s_instance;
54 }
55
61 void PerfStats::start( bool clear ) {
62
63 lock_t lock (s_mutex);
64 // Return right away if we are running already:
65 if( m_running ) return;
66
67 // Clear the statistics collected so far if required:
68 if( clear ) IOStats::instance().stats().Clear();
69
70 // Let the user know what we're doing:
71 Info( "start", "Starting performance monitoring" );
72
73 // Record the starting time:
74 m_startTime = TTimeStamp();
75 // Remember that we are running:
76 m_running = true;
77
78 return;
79 }
80
84 void PerfStats::stop() {
85
86 lock_t lock (s_mutex);
87 // Return right away if we are not running:
88 if( ! m_running ) return;
89
90 // Calculate the time elapsed from when the analysis started:
91 const ::Double_t elapsed = TTimeStamp().AsDouble() -
92 m_startTime;
93 // Save it:
94 ReadStats& stats = IOStats::instance().stats();
95 stats.setProcessTime( stats.processTime() + elapsed );
96
97 // Remember that we are stopped:
98 m_running = false;
99
100 // Let the user know what we've done:
101 Info( "stop", "Performance monitoring stopped after %s",
102 Utils::timeToString( elapsed ).c_str() );
103
104 return;
105 }
106
107 void PerfStats::SimpleEvent( EEventType type ) {
108
109 // Forward the call if possible:
110 if( m_otherPerfStats ) {
111 m_otherPerfStats->SimpleEvent( type );
112 }
113
114 return;
115 }
116
117 void PerfStats::PacketEvent( const char* slave, const char* slavename,
118 const char* filename,
119 ::Long64_t eventsprocessed,
120 ::Double_t latency,
121 ::Double_t proctime, ::Double_t cputime,
122 ::Long64_t bytesRead ) {
123
124 // Forward the call if possible:
125 if( m_otherPerfStats ) {
126 m_otherPerfStats->PacketEvent( slave, slavename, filename,
127 eventsprocessed, latency, proctime,
128 cputime, bytesRead );
129 }
130
131 return;
132 }
133
134 void PerfStats::FileEvent( const char* slave, const char* slavename,
135 const char* nodename, const char* filename,
136 ::Bool_t isStart ) {
137
138 // Forward the call if possible:
139 if( m_otherPerfStats ) {
140 m_otherPerfStats->FileEvent( slave, slavename, nodename, filename,
141 isStart );
142 }
143
144 return;
145 }
146
147 void PerfStats::FileOpenEvent( ::TFile* file, const char* filename,
148 ::Double_t start ) {
149
150 // Forward the call if possible:
151 if( m_otherPerfStats ) {
152 m_otherPerfStats->FileOpenEvent( file, filename, start );
153 }
154
155 return;
156 }
157
167 void PerfStats::FileReadEvent( ::TFile* file, ::Int_t len,
168 ::Double_t start ) {
169
170 // Do the calculation without delay:
171 const ::Double_t tnow = TTimeStamp();
172 const ::Double_t dtime = tnow - start;
173
174 // Accumulate the reading time statistics:
175 ReadStats& stats = IOStats::instance().stats();
176 stats.setReadTime( stats.readTime() + dtime );
177
178 // Accumulate the amount of read data:
179 stats.setBytesRead( stats.bytesRead() + len );
180 stats.setFileReads( stats.fileReads() + 1 );
181
182 // Forward the call if possible:
183 if( m_otherPerfStats ) {
184 m_otherPerfStats->FileReadEvent( file, len, start );
185 }
186
187 return;
188 }
189
199 void PerfStats::UnzipEvent( ::TObject* tree, ::Long64_t pos,
200 ::Double_t start, ::Int_t complen,
201 ::Int_t objlen ) {
202
203 // Do the calculation without delay:
204 const ::Double_t tnow = TTimeStamp();
205 const ::Double_t dtime = tnow - start;
206
207 // Just accumulate the zipping time statistics:
208 ReadStats& stats = IOStats::instance().stats();
209 stats.setUnzipTime( stats.unzipTime() + dtime );
210
211 // Get the cache size from the tree:
212 ::TTree* t = dynamic_cast< ::TTree* >( tree );
213 if( ! t ) {
214 Warning( "UnzipEvent", "Couldn't cast object to TTree" );
215 } else {
216 stats.setCacheSize( t->GetCacheSize() );
217 }
218
219 // Forward the call if possible:
220 if( m_otherPerfStats ) {
221 m_otherPerfStats->UnzipEvent( tree, pos, start, complen, objlen );
222 }
223
224 return;
225 }
226
227 void PerfStats::RateEvent( ::Double_t proctime, ::Double_t deltatime,
228 ::Long64_t eventsprocessed,
229 ::Long64_t bytesRead ) {
230
231 // Forward the call if possible:
232 if( m_otherPerfStats ) {
233 m_otherPerfStats->RateEvent( proctime, deltatime, eventsprocessed,
234 bytesRead );
235 }
236
237 return;
238 }
239
248 void PerfStats::SetBytesRead( ::Long64_t num ) {
249
250 // Forward the call if possible:
251 if( m_otherPerfStats ) {
252 m_otherPerfStats->SetBytesRead( num );
253 }
254
255 return;
256 }
257
258 ::Long64_t PerfStats::GetBytesRead() const {
259
260 // Forward the call if possible:
261 if( m_otherPerfStats ) {
262 return m_otherPerfStats->GetBytesRead();
263 } else {
264 return IOStats::instance().stats().bytesRead();
265 }
266 }
267
274 void PerfStats::SetNumEvents( ::Long64_t num ) {
275
276 // Forward the call if possible:
277 if( m_otherPerfStats ) {
278 m_otherPerfStats->SetNumEvents( num );
279 }
280
281 return;
282 }
283
290 ::Long64_t PerfStats::GetNumEvents() const {
291
292 // Forward the call if possible:
293 if( m_otherPerfStats ) {
294 return m_otherPerfStats->GetNumEvents();
295 }
296
297 return 0;
298 }
299
300 /* Some methods that are pure virtual in the basaclass and need
301 a definition - forwarding them to the actuall ROOT TPerfStats
302 new in ROOT 6.14
303 */
304 void PerfStats::PrintBasketInfo( Option_t *option ) const {
305 if( m_otherPerfStats ) m_otherPerfStats->PrintBasketInfo( option );
306 }
307
308 void PerfStats::UpdateBranchIndices( TObjArray *branches ) {
309 if( m_otherPerfStats ) m_otherPerfStats->UpdateBranchIndices( branches );
310 }
311
312 #define FWD_CALL(CALL) \
313 void PerfStats::CALL( TBranch *b, size_t basketNumber ) { \
314 if( m_otherPerfStats ) m_otherPerfStats->CALL( b, basketNumber ); \
315 } \
316 void PerfStats::CALL( size_t bi, size_t basketNumber ) { \
317 if( m_otherPerfStats ) m_otherPerfStats->CALL( bi, basketNumber ); \
318 } struct dummyforsemi
319
320 FWD_CALL(SetLoaded);
321 FWD_CALL(SetLoadedMiss);
322 FWD_CALL(SetMissed);
323 FWD_CALL(SetUsed);
324 #undef FWD_CALL
325
332 PerfStats::PerfStats()
333 : m_otherPerfStats( nullptr ), m_running( false ), m_startTime( 0.0 ),
334 m_tree( nullptr ), m_file( nullptr ), m_treeWarningPrinted( false ) {
335
336 // locked via instance().
337
338 // Remember a possible former performance monitoring object:
339 if( gPerfStats && ( gPerfStats != this ) ) {
340 m_otherPerfStats = gPerfStats;
341 Info( "PerfStats",
342 "Will forward calls to former gPerfStats object" );
343 }
344
345 // This object is now the performance monitoring object:
346 gPerfStats = this;
347 }
348
349#if ROOT_VERSION_CODE >= ROOT_VERSION( 6, 23, 2 )
353 void PerfStats::SetFile( TFile* file ) {
354
355 m_file = file;
356 }
357#endif // ROOT version
358
359} // namespace xAOD
#define FWD_CALL(CALL)
std::lock_guard< std::mutex > lock_t
@ Info
Definition ZDCMsg.h:20
TChain * tree
TFile * file