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"
11 #include "GaudiKernel/MsgStream.h"
14 
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 
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 
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 "
72  m_inFullAudit = true;
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;
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;
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  {
121  alreadyRunning() )
122  {
123  stopAudit();
124  }
125  else
126  {
128  }
129  }
130  if ( m_audit && !m_inFullAudit && !alreadyRunning() )
131  {
132  startAudit();
133  }
134  }
135  }
136  }
137 
138  public:
139 
141  {
142  if ( !m_skipSequencers || !isSequencer(i) )
143  {
144  before(type,i->name());
145  }
146  }
147 
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  {
180  << "Auditor already running. Cannot be started for " << s
181  << endmsg;
182  }
183  }
184  }
185 
187  {
188  if ( !m_skipSequencers || !isSequencer(i) )
189  {
190  std::ostringstream t;
191  t << type;
192  after(t.str(),i,sc);
193  }
194  }
195 
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
233 
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 
265 
266  int m_freq;
267 
268  bool m_audit;
269 
270  unsigned long long m_nEvts;
271 
273 
274  unsigned long long m_nSampleEvents;
275 
276  unsigned long long m_sampleEventCount;
277 
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 
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 
410  {
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  {
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 
520 
521 }
const std::string BeginEvent
Processing of a new event has started.
Definition: Incident.h:60
StatusCode finalize()
Finalize the auditor base.
HeapLeakChecker * m_checker
void beforeBeginRun(INamedInterface *i)
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:24
std::string m_startedBy
Name of the component we are currently auditing.
HeapChecker(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
void beforeReinitialize(INamedInterface *i)
void stopAudit()
stop a full event audit
StatusCode service(const std::string &name, T *&svc, bool createIf=false) const
Access a service by name, creating it if it doesn't already exist.
Definition: Auditor.h:117
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:26
virtual const std::string & name() const
Retrieve the name of the instance.
Definition: Auditor.cpp:218
const std::string & type() const
Access to the incident type.
Definition: Incident.h:34
StandardEventType
Defines the standard (= used by the framework) auditable event types.
Definition: IAuditor.h:24
virtual void google_before(const std::string &s)=0
Start the google tool.
virtual ~AuditorBase()
Destructor.
bool m_audit
Internal flag to say if auditing is enabled or not for the current event.
void startAudit()
Start a full event audit.
const CustomEventType & CustomEventTypeRef
Used in function calls for optimization purposes.
Definition: IAuditor.h:41
unsigned long long m_nSampleEvents
Number of events to include in a full event audit.
virtual bool alreadyRunning()=0
check if we are already running the tool
StatusCode initialize()
Initialize the auditor base.
bool m_inFullAudit
Internal flag to indicate if we are current in a full event audit.
bool isFailure() const
Test for a status code of FAILURE.
Definition: StatusCode.h:72
unsigned long long m_sampleEventCount
Internal count of the number of events currently processed during an audit.
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:35
int m_freq
The frequency to audit events. -1 means all events.
void before(CustomEventTypeRef type, INamedInterface *i)
Audit the start of a custom "event".
virtual const std::string & name() const =0
Retrieve the name of the instance.
bool alreadyRunning()
check if we are already running the tool
StatusCode initialize()
Initialize the auditor base.
Property * declareProperty(const std::string &name, T &property, const std::string &doc="none") const
Declare the named property.
Definition: Auditor.h:233
void google_after(const std::string &)
stop the google tool
string type
Definition: gaudirun.py:126
void afterExecute(INamedInterface *i, const StatusCode &s)
unsigned long long m_nEvts
Number of events processed.
bool isValid() const
Allow for check if smart pointer is valid.
Definition: SmartIF.h:51
void after(CustomEventTypeRef type, INamedInterface *i, const StatusCode &sc)
Audit the end of a custom "event".
void beforeExecute(INamedInterface *i)
void google_before(const std::string &s)
Start the google tool.
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:30
void google_after(const std::string &s)
stop the google tool
Base class used to extend a class implementing other interfaces.
Definition: extends.h:10
std::vector< std::string > m_list
Any component in this list will be audited. If empty, all will be done.
Auditor using the Google Heap Checker.
void afterBeginRun(INamedInterface *i)
void before(CustomEventTypeRef, const std::string &s)
Audit the start of a custom "event" for callers that do not implement INamedInterface.
bool m_fullEventAudit
Flag to indicate if full event auditing is enabled or not.
void google_before(const std::string &s)
Start the google tool.
void google_after(const std::string &s)
stop the google tool
bool alreadyRunning()
check if we are already running the tool
HeapProfiler(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
SmartIF< ISvcLocator > & serviceLocator() const
The standard service locator.
Definition: Auditor.cpp:236
void afterFinalize(INamedInterface *i)
void afterReinitialize(INamedInterface *i)
void afterInitialize(INamedInterface *i)
std::vector< std::string > m_when
When to audit the algorithms.
void beforeEndRun(INamedInterface *i)
IInterface compliant class extending IInterface with the name() method.
void beforeInitialize(INamedInterface *i)
void beforeFinalize(INamedInterface *i)
Base class for all Incidents (computing events).
Definition: Incident.h:16
void before(StandardEventType type, INamedInterface *i)
The following methods are meant to be implemented by the child class...
void handle(const Incident &incident)
Implement the handle method for the Incident service.
string s
Definition: gaudirun.py:210
void google_before(const std::string &s)
Start the google tool.
MsgStream m_log
Messaging object.
void after(CustomEventTypeRef, const std::string &s, const StatusCode &)
Audit the end of a custom "event" for callers that do not implement INamedInterface.
void before(StandardEventType type, const std::string &s)
Audit the start of a standard "event" for callers that do not implement INamedInterface.
void after(StandardEventType type, INamedInterface *i, const StatusCode &sc)
Audit the end of a standard "event".
CPUProfiler(const std::string &name, ISvcLocator *pSvcLocator)
std::vector< std::string > m_veto
Veto list. Any component in this list will not be audited.
AuditorBase(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
void afterEndRun(INamedInterface *i)
unsigned long long m_eventsToSkip
Number of events to skip before auditing.
Base for Google Auditors.
virtual void google_after(const std::string &s)=0
stop the google tool
bool alreadyRunning()
check if we are already running the tool
list i
Definition: ana.py:128
Auditor using the Google CPU Profiler.
bool m_skipSequencers
Boolean indicating if sequencers should be skipped or not.
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:243
void after(StandardEventType type, const std::string &s, const StatusCode &sc)
Audit the end of a standard "event" for callers that do not implement INamedInterface.
Auditor based on the Google Heap Profiler.
bool isSequencer(INamedInterface *i) const
Check if the component in question is a GaudiSequencer or a Sequencer.