| # Gaudi Framework, version v25r0 |

Home |  | Generated: Mon Feb 17 2014

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
GoogleAuditor.cpp
Go to the documentation of this file.
1
2 #include <vector>
3 #include <string>
4 #include <utility>
5 #include <memory>
6 #include <algorithm>
7
8 #include "GaudiKernel/Auditor.h"
9 #include "GaudiKernel/IAuditorSvc.h"
10 #include "GaudiKernel/GaudiException.h"
11 #include "GaudiKernel/MsgStream.h"
12 #include "GaudiKernel/IIncidentListener.h"
13 #include "GaudiKernel/IIncidentSvc.h"
14
15 #include "GaudiAlg/GaudiSequencer.h"
16 #include "GaudiAlg/Sequencer.h"
17
18 #include "boost/assign/list_of.hpp"
19
20 #include "google/heap-profiler.h"
21 #include "google/heap-checker.h"
22 #include "google/profiler.h"
23
24 namespace Google
25 {
26
34 class AuditorBase : public extends1<Auditor, IIncidentListener>
35 {
36
37 public:
38
40 AuditorBase( const std::string& name, ISvcLocator* pSvcLocator);
41
43 virtual ~AuditorBase() { }
44
46 StatusCode initialize()
47 {
48 m_log << MSG::INFO << "Initialised" << endmsg;
49
50 SmartIF<IIncidentSvc> inSvc(serviceLocator()->service("IncidentSvc"));
51 if ( ! inSvc.isValid() ) return StatusCode::FAILURE;
52
53 inSvc->addListener( this, IncidentType::BeginEvent );
54
55 return StatusCode::SUCCESS;
56 }
57
59 StatusCode finalize()
60 {
61 if ( alreadyRunning() ) stopAudit();
62 return StatusCode::SUCCESS;
63 }
64
65 private:
66
68 void startAudit()
69 {
70 m_log << MSG::INFO << " -> Starting full audit from event " << m_nEvts << " to "
71 << m_nEvts+m_nSampleEvents << endmsg;
72 m_inFullAudit = true;
73 m_sampleEventCount = 1;
74 std::ostringstream t;
75 t << "FULL-Events" << m_nEvts << "To" << m_nEvts+m_nSampleEvents ;
76 google_before(t.str());
77 }
78
80 void stopAudit()
81 {
82 m_log << MSG::INFO << " -> Stopping full audit" << endmsg;
83 std::ostringstream t;
84 t << "FULL-Events" << m_nEvts << "To" << m_nEvts+m_nSampleEvents ;
85 google_after(t.str());
86 m_inFullAudit = false;
87 m_sampleEventCount = 0;
88 }
89
92 bool isSequencer( INamedInterface* i ) const
93 {
94 return ( dynamic_cast<GaudiSequencer*>(i) != NULL ||
95 dynamic_cast<Sequencer*>(i) != NULL );
96 }
97
98 public:
99
105 void handle( const Incident& incident )
106 {
107 if ( IncidentType::BeginEvent == incident.type() )
108 {
109 ++m_nEvts;
110 m_audit = ( m_nEvts > m_eventsToSkip &&
111 ( m_freq < 0 ||
112 m_nEvts == 1 ||
113 m_nEvts % m_freq == 0 ) );
114 m_log << MSG::DEBUG << "Event " << m_nEvts
115 << " Audit=" << m_audit << endmsg;
116 if ( m_fullEventAudit )
117 {
118 if ( m_inFullAudit )
119 {
120 if ( m_sampleEventCount >= m_nSampleEvents &&
121 alreadyRunning() )
122 {
123 stopAudit();
124 }
125 else
126 {
127 ++m_sampleEventCount;
128 }
129 }
130 if ( m_audit && !m_inFullAudit && !alreadyRunning() )
131 {
132 startAudit();
133 }
134 }
135 }
136 }
137
138 public:
139
140 void before(StandardEventType type, INamedInterface* i)
141 {
142 if ( !m_skipSequencers || !isSequencer(i) )
143 {
144 before(type,i->name());
145 }
146 }
147
148 void before(CustomEventTypeRef type, INamedInterface* i)
149 {
150 if ( !m_skipSequencers || !isSequencer(i) )
151 {
152 before(type,i->name());
153 }
154 }
155
156 void before(StandardEventType type, const std::string& s)
157 {
158 std::ostringstream t;
159 t << type;
160 before(t.str(),s);
161 }
162
163 void before(CustomEventTypeRef, const std::string& s)
164 {
165 if ( !m_fullEventAudit && m_audit &&
166 std::find(m_veto.begin(),m_veto.end(),s) == m_veto.end() &&
167 ( m_list.empty() || std::find(m_list.begin(),m_list.end(),s) != m_list.end() ) )
168 {
169 if ( !alreadyRunning() )
170 {
171 m_log << MSG::INFO << "Starting Auditor for " << s << endmsg;
172 m_startedBy = s;
173 std::ostringstream t;
174 t << s << "-Event" << m_nEvts;
175 google_before(t.str());
176 }
177 else
178 {
179 m_log << MSG::WARNING
180 << "Auditor already running. Cannot be started for " << s
181 << endmsg;
182 }
183 }
184 }
185
186 void after(StandardEventType type, INamedInterface* i, const StatusCode& sc)
187 {
188 if ( !m_skipSequencers || !isSequencer(i) )
189 {
190 std::ostringstream t;
191 t << type;
192 after(t.str(),i,sc);
193 }
194 }
195
196 void after(CustomEventTypeRef type, INamedInterface* i, const StatusCode& sc)
197 {
198 if ( !m_skipSequencers || !isSequencer(i) )
199 {
200 after(type,i->name(),sc);
201 }
202 }
203
204 void after(StandardEventType type, const std::string& s, const StatusCode& sc)
205 {
206 std::ostringstream t;
207 t << type;
208 after(t.str(),s,sc);
209 }
210
211 void after(CustomEventTypeRef, const std::string& s, const StatusCode&)
212 {
213 if ( !m_fullEventAudit && m_audit &&
214 std::find(m_veto.begin(),m_veto.end(),s) == m_veto.end() &&
215 ( m_list.empty() || std::find(m_list.begin(),m_list.end(),s) != m_list.end() ) )
216 {
217 if ( s == m_startedBy )
218 {
219 std::ostringstream t;
220 t << s << "-Event" << m_nEvts;
221 google_after(t.str());
222 }
223 }
224 }
225
226 // Obsolete methods
227 void beforeInitialize (INamedInterface *i) { return before(IAuditor::Initialize,i); }
228 void beforeReinitialize(INamedInterface *i) { return before(IAuditor::ReInitialize,i); }
229 void beforeExecute (INamedInterface *i) { return before(IAuditor::Execute,i); }
230 void beforeBeginRun (INamedInterface *i) { return before(IAuditor::BeginRun,i); }
231 void beforeEndRun (INamedInterface *i) { return before(IAuditor::EndRun,i); }
232 void beforeFinalize (INamedInterface *i) { return before(IAuditor::Finalize,i); }
233
234 void afterInitialize (INamedInterface *i) { return after(IAuditor::Initialize,i,StatusCode::SUCCESS); }
235 void afterReinitialize (INamedInterface *i) { return after(IAuditor::ReInitialize,i,StatusCode::SUCCESS); }
236 void afterExecute (INamedInterface *i, const StatusCode& s) { return after(IAuditor::Execute,i,s); }
237 void afterBeginRun (INamedInterface *i) { return after(IAuditor::BeginRun,i,StatusCode::SUCCESS); }
238 void afterEndRun (INamedInterface *i) { return after(IAuditor::EndRun,i,StatusCode::SUCCESS); }
239 void afterFinalize (INamedInterface *i) { return after(IAuditor::Finalize,i,StatusCode::SUCCESS); }
240
241 protected:
242
244 virtual void google_before(const std::string& s) = 0;
245
247 virtual void google_after(const std::string& s) = 0;
248
250 virtual bool alreadyRunning() = 0;
251
252 protected:
253
254 mutable MsgStream m_log;
255
256 private:
257
258 std::vector<std::string> m_when;
259 std::vector<std::string> m_veto;
260 std::vector<std::string> m_list;
261
262 unsigned long long m_eventsToSkip;
263
264 bool m_skipSequencers;
265
266 int m_freq;
267
268 bool m_audit;
269
270 unsigned long long m_nEvts;
271
272 bool m_fullEventAudit;
273
274 unsigned long long m_nSampleEvents;
275
276 unsigned long long m_sampleEventCount;
277
278 bool m_inFullAudit;
279
280 std::string m_startedBy;
281
282 };
283
284 AuditorBase::AuditorBase( const std::string& name,
285 ISvcLocator* pSvcLocator )
286 : base_class ( name , pSvcLocator )
287 , m_log ( msgSvc() , name )
288 , m_audit ( false )
289 , m_nEvts ( 0 )
290 , m_sampleEventCount( 0 )
291 , m_inFullAudit ( false )
292 {
293 {
294 // Note: 'tmp' is needed to avoid an issue with list_of and C++11.
295 const std::vector<std::string> tmp =
296 boost::assign::list_of
297 ("Initialize")
298 ("ReInitialize")
299 ("Execute")
300 ("BeginRun")
301 ("EndRun")
302 ("Finalize");
303 m_when = tmp;
304 }
305
306 declareProperty("ActivateAt", m_when,
307 "List of phases to activate the Auditoring during" );
308 declareProperty("DisableFor", m_veto,
309 "List of component names to disable the auditing for" );
310 declareProperty("EnableFor", m_list );
311 declareProperty("ProfileFreq", m_freq = -1,
312 "The frequence to audit events. -1 means all events" );
313 declareProperty("DoFullEventProfile", m_fullEventAudit = false,
314 "If true, instead of individually auditing components, the full event (or events) will be audited in one go" );
315 declareProperty("FullEventNSampleEvents", m_nSampleEvents = 1,
316 "The number of events to include in a full event audit, if enabled" );
317 declareProperty("SkipEvents", m_eventsToSkip = 0,
318 "Number of events to skip before activating the auditing" );
319 declareProperty("SkipSequencers", m_skipSequencers = true,
320 "If true, auditing will be skipped for Sequencer objects." );
321 }
322
336 class HeapProfiler : public AuditorBase
337 {
338
339 public:
340
342 HeapProfiler( const std::string& name, ISvcLocator* pSvcLocator)
343 : AuditorBase( name, pSvcLocator )
344 {
345 declareProperty( "DumpHeapProfiles", m_dumpProfileHeaps = true );
346 declareProperty( "PrintProfilesToLog", m_printProfilesToLog = false );
347 }
348
349 protected:
350
351 void google_before(const std::string& s)
352 {
353 HeapProfilerStart(s.c_str());
354 }
355
356 void google_after(const std::string& s)
357 {
358 if ( m_dumpProfileHeaps )
359 {
360 HeapProfilerDump(s.c_str());
361 }
362 if ( m_printProfilesToLog )
363 {
364 const char * profile = GetHeapProfile();
365 m_log << MSG::INFO << profile << endmsg;
366 delete profile;
367 }
368 HeapProfilerStop();
369 }
370
371 bool alreadyRunning() { return IsHeapProfilerRunning(); }
372
373 private:
374
375 bool m_dumpProfileHeaps;
376 bool m_printProfilesToLog;
377
378 };
379
393 class HeapChecker : public AuditorBase
394 {
395
396 public:
397
399 HeapChecker( const std::string& name, ISvcLocator* pSvcLocator)
400 : AuditorBase ( name, pSvcLocator ),
401 m_enabled ( true ),
402 m_checker ( NULL )
403 { }
404
405 virtual ~HeapChecker() { delete m_checker; }
406
407 public:
408
409 StatusCode initialize()
410 {
411 const StatusCode sc = AuditorBase::initialize();
412 if ( sc.isFailure() ) return sc;
413
414 const char * HEAPCHECK = getenv("HEAPCHECK");
415 if ( !HEAPCHECK )
416 {
417 m_log << MSG::FATAL
418 << "Environment variable HEAPCHECK must be set to 'local'"
419 << endmsg;
420 return StatusCode::FAILURE;
421 }
422 if ( std::string(HEAPCHECK) != "local" )
423 {
424 m_log << MSG::WARNING
425 << "Environment variable HEAPCHECK is set to " << HEAPCHECK
426 << " Partial Program Heap Checking is disabled"
427 << endmsg;
428 m_enabled = false;
429 }
430
431 return sc;
432 }
433
434 protected:
435
436 void google_before(const std::string& s)
437 {
438 if ( m_enabled && !m_checker )
439 {
440 m_checker = new HeapLeakChecker(s.c_str());
441 }
442 }
443
444 void google_after(const std::string& s)
445 {
446 if ( m_enabled && m_checker )
447 {
448 if ( ! m_checker->NoLeaks() )
449 {
450 m_log << MSG::WARNING << "Leak detected for " << s << endmsg;
451 }
452 delete m_checker;
453 m_checker = NULL;
454 }
455 }
456
457 bool alreadyRunning() { return m_enabled && m_checker != NULL ; }
458
459 private:
460
461 bool m_enabled;
462 HeapLeakChecker * m_checker;
463
464 };
465
479 class CPUProfiler : public AuditorBase
480 {
481
482 public:
483
484 CPUProfiler( const std::string& name, ISvcLocator* pSvcLocator )
485 : AuditorBase ( name, pSvcLocator ),
486 m_running ( false )
487 { }
488
489 protected:
490
491 void google_before(const std::string& s)
492 {
493 if ( !m_running )
494 {
495 m_running = true;
496 ProfilerStart((s+".prof").c_str());
497 }
498 }
499
500 void google_after(const std::string&)
501 {
502 if ( m_running )
503 {
504 ProfilerStop();
505 m_running = false;
506 }
507 }
508
509 bool alreadyRunning() { return m_running; }
510
511 private:
512
513 bool m_running;
514
515 };
516
517 DECLARE_COMPONENT( HeapProfiler )
518 DECLARE_COMPONENT( HeapChecker )
519 DECLARE_COMPONENT( CPUProfiler )
520
521 }