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  // add a listener for begin event
51  SmartIF<IIncidentSvc> inSvc(serviceLocator()->service("IncidentSvc"));
52  if ( ! inSvc.isValid() ) return StatusCode::FAILURE;
53  inSvc->addListener( this, IncidentType::BeginEvent );
54 
55  // sort various lists for speed when searching
56  std::sort( m_when.begin(), m_when.end() );
57  std::sort( m_veto.begin(), m_veto.end() );
58  std::sort( m_list.begin(), m_list.end() );
59 
60  return StatusCode::SUCCESS;
61  }
62 
65  {
66  if ( alreadyRunning() ) stopAudit();
67  return StatusCode::SUCCESS;
68  }
69 
70  private:
71 
73  inline void startAudit()
74  {
75  m_log << MSG::INFO << " -> Starting full audit from event " << m_nEvts << " to "
77  m_inFullAudit = true;
79  std::ostringstream t;
80  t << "FULL-Events" << m_nEvts << "To" << m_nEvts+m_nSampleEvents ;
81  google_before(t.str());
82  }
83 
85  inline void stopAudit()
86  {
87  m_log << MSG::INFO << " -> Stopping full audit" << endmsg;
88  std::ostringstream t;
89  t << "FULL-Events" << m_nEvts << "To" << m_nEvts+m_nSampleEvents ;
90  google_after(t.str());
91  m_inFullAudit = false;
93  }
94 
97  inline bool isSequencer( INamedInterface* i ) const
98  {
99  return ( dynamic_cast<GaudiSequencer*>(i) != NULL ||
100  dynamic_cast<Sequencer*>(i) != NULL );
101  }
102 
104  inline bool isPhaseEnabled( const CustomEventTypeRef& type ) const
105  {
106  return ( std::find(m_when.begin(),m_when.end(),type) != m_when.end() );
107  }
108 
110  inline bool isComponentEnabled( const std::string& name ) const
111  {
112  return ( std::find(m_veto.begin(),m_veto.end(),name) == m_veto.end() &&
113  ( m_list.empty() ||
114  std::find(m_list.begin(),m_list.end(),name) != m_list.end() ) );
115  }
116 
117  // Construct the dump name based on processing phase and component name
118  std::string getDumpName( const CustomEventTypeRef& type,
119  const std::string& name ) const
120  {
121  std::ostringstream t;
122  t << name << "-" << type;
123  if ( type == "Execute" ) t << "-Event" << m_nEvts;
124  return t.str();
125  }
126 
127  public:
128 
134  void handle( const Incident& incident )
135  {
136  if ( IncidentType::BeginEvent == incident.type() )
137  {
138  ++m_nEvts;
140  ( m_freq < 0 ||
141  m_nEvts == 1 ||
142  m_nEvts % m_freq == 0 ) );
143  m_log << MSG::DEBUG << "Event " << m_nEvts
144  << " Audit=" << m_audit << endmsg;
145  if ( m_fullEventAudit )
146  {
147  if ( m_inFullAudit )
148  {
150  alreadyRunning() )
151  {
152  stopAudit();
153  }
154  else
155  {
157  }
158  }
159  if ( m_audit && !m_inFullAudit && !alreadyRunning() )
160  {
161  startAudit();
162  }
163  }
164  }
165  }
166 
167  public:
168 
170  {
171  if ( !m_skipSequencers || !isSequencer(i) )
172  {
173  before( type, i->name() );
174  }
175  }
176 
178  {
179  if ( !m_skipSequencers || !isSequencer(i) )
180  {
181  before( type, i->name() );
182  }
183  }
184 
185  void before(StandardEventType type, const std::string& s)
186  {
187  std::ostringstream t;
188  t << type;
189  before( t.str(), s );
190  }
191 
192  void before(CustomEventTypeRef type, const std::string& s)
193  {
194  if ( !m_fullEventAudit && m_audit &&
195  isPhaseEnabled(type) && isComponentEnabled(s) )
196  {
197  if ( !alreadyRunning() )
198  {
199  m_log << MSG::INFO
200  << "Starting Auditor for " << s << ":" << type
201  << endmsg;
202  m_startedBy = s;
203  google_before( getDumpName(type,s) );
204  }
205  else
206  {
208  << "Auditor already running. Cannot be started for " << s
209  << endmsg;
210  }
211  }
212  }
213 
215  {
216  if ( !m_skipSequencers || !isSequencer(i) )
217  {
218  std::ostringstream t;
219  t << type;
220  after( t.str(), i, sc );
221  }
222  }
223 
225  {
226  if ( !m_skipSequencers || !isSequencer(i) )
227  {
228  after( type, i->name(), sc );
229  }
230  }
231 
232  void after(StandardEventType type, const std::string& s, const StatusCode& sc)
233  {
234  std::ostringstream t;
235  t << type;
236  after( t.str(), s, sc );
237  }
238 
239  void after(CustomEventTypeRef type, const std::string& s, const StatusCode&)
240  {
241  if ( !m_fullEventAudit && m_audit &&
242  isPhaseEnabled(type) && isComponentEnabled(s) )
243  {
244  if ( s == m_startedBy ) { google_after( getDumpName(type,s) ); }
245  }
246  }
247 
248  // Obsolete methods
255 
262 
263  protected:
264 
266  virtual void google_before(const std::string& s) = 0;
267 
269  virtual void google_after(const std::string& s) = 0;
270 
272  virtual bool alreadyRunning() = 0;
273 
274  protected:
275 
276  mutable MsgStream m_log;
277 
278  private:
279 
280  std::vector<std::string> m_when;
281  std::vector<std::string> m_veto;
282  std::vector<std::string> m_list;
283 
284  unsigned long long m_eventsToSkip;
285 
287 
288  int m_freq;
289 
290  bool m_audit;
291 
292  unsigned long long m_nEvts;
293 
295 
296  unsigned long long m_nSampleEvents;
297 
298  unsigned long long m_sampleEventCount;
299 
301 
302  std::string m_startedBy;
303 
304  };
305 
306  AuditorBase::AuditorBase( const std::string& name,
307  ISvcLocator* pSvcLocator )
308  : base_class ( name , pSvcLocator )
309  , m_log ( msgSvc() , name )
310  , m_audit ( true )
311  , m_nEvts ( 0 )
312  , m_sampleEventCount( 0 )
313  , m_inFullAudit ( false )
314  {
315  {
316  // Note: 'tmp' is needed to avoid an issue with list_of and C++11.
317  const std::vector<std::string> tmp =
318  boost::assign::list_of
319  ("Initialize")
320  ("ReInitialize")
321  ("Execute")
322  ("BeginRun")
323  ("EndRun")
324  ("Finalize");
325  m_when = tmp;
326  }
327 
328  declareProperty("ActivateAt", m_when,
329  "List of phases to activate the Auditoring during" );
330  declareProperty("DisableFor", m_veto,
331  "List of component names to disable the auditing for" );
332  declareProperty("EnableFor", m_list );
333  declareProperty("ProfileFreq", m_freq = -1,
334  "The frequence to audit events. -1 means all events" );
335  declareProperty("DoFullEventProfile", m_fullEventAudit = false,
336  "If true, instead of individually auditing components, the full event (or events) will be audited in one go" );
337  declareProperty("FullEventNSampleEvents", m_nSampleEvents = 1,
338  "The number of events to include in a full event audit, if enabled" );
339  declareProperty("SkipEvents", m_eventsToSkip = 0,
340  "Number of events to skip before activating the auditing" );
341  declareProperty("SkipSequencers", m_skipSequencers = true,
342  "If true, auditing will be skipped for Sequencer objects." );
343  }
344 
358  class HeapProfiler : public AuditorBase
359  {
360 
361  public:
362 
364  HeapProfiler( const std::string& name, ISvcLocator* pSvcLocator)
365  : AuditorBase( name, pSvcLocator )
366  {
367  declareProperty( "DumpHeapProfiles", m_dumpProfileHeaps = true );
368  declareProperty( "PrintProfilesToLog", m_printProfilesToLog = false );
369  }
370 
371  protected:
372 
373  void google_before(const std::string& s)
374  {
375  HeapProfilerStart(s.c_str());
376  }
377 
378  void google_after(const std::string& s)
379  {
380  if ( m_dumpProfileHeaps )
381  {
382  HeapProfilerDump(s.c_str());
383  }
384  if ( m_printProfilesToLog )
385  {
386  const char * profile = GetHeapProfile();
387  m_log << MSG::INFO << profile << endmsg;
388  delete profile;
389  }
390  HeapProfilerStop();
391  }
392 
393  bool alreadyRunning() { return IsHeapProfilerRunning(); }
394 
395  private:
396 
399 
400  };
401 
415  class HeapChecker : public AuditorBase
416  {
417 
418  public:
419 
421  HeapChecker( const std::string& name, ISvcLocator* pSvcLocator)
422  : AuditorBase ( name, pSvcLocator ),
423  m_enabled ( true ),
424  m_checker ( NULL )
425  { }
426 
427  virtual ~HeapChecker() { delete m_checker; }
428 
429  public:
430 
432  {
434  if ( sc.isFailure() ) return sc;
435 
436  const char * HEAPCHECK = getenv("HEAPCHECK");
437  if ( !HEAPCHECK )
438  {
439  m_log << MSG::FATAL
440  << "Environment variable HEAPCHECK must be set to 'local'"
441  << endmsg;
442  return StatusCode::FAILURE;
443  }
444  if ( std::string(HEAPCHECK) != "local" )
445  {
447  << "Environment variable HEAPCHECK is set to " << HEAPCHECK
448  << " Partial Program Heap Checking is disabled"
449  << endmsg;
450  m_enabled = false;
451  }
452 
453  return sc;
454  }
455 
456  protected:
457 
458  void google_before(const std::string& s)
459  {
460  if ( m_enabled && !m_checker )
461  {
462  m_checker = new HeapLeakChecker(s.c_str());
463  }
464  }
465 
466  void google_after(const std::string& s)
467  {
468  if ( m_enabled && m_checker )
469  {
470  if ( ! m_checker->NoLeaks() )
471  {
472  m_log << MSG::WARNING << "Leak detected for " << s << endmsg;
473  }
474  delete m_checker;
475  m_checker = NULL;
476  }
477  }
478 
479  bool alreadyRunning() { return m_enabled && m_checker != NULL ; }
480 
481  private:
482 
483  bool m_enabled;
484  HeapLeakChecker * m_checker;
485 
486  };
487 
501  class CPUProfiler : public AuditorBase
502  {
503 
504  public:
505 
506  CPUProfiler( const std::string& name, ISvcLocator* pSvcLocator )
507  : AuditorBase ( name, pSvcLocator ),
508  m_running ( false )
509  { }
510 
511  protected:
512 
513  void google_before(const std::string& s)
514  {
515  if ( !m_running )
516  {
517  m_running = true;
518  ProfilerStart((s+".prof").c_str());
519  }
520  }
521 
522  void google_after(const std::string&)
523  {
524  if ( m_running )
525  {
526  ProfilerStop();
527  m_running = false;
528  }
529  }
530 
531  bool alreadyRunning() { return m_running; }
532 
533  private:
534 
535  bool m_running;
536 
537  };
538 
542 
543 }
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:119
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 before(CustomEventTypeRef type, const std::string &s)
Audit the start of a custom "event" for callers that do not implement INamedInterface.
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:85
unsigned long long m_sampleEventCount
Internal count of the number of events currently processed during an audit.
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:36
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:235
void google_after(const std::string &)
stop the google tool
string type
Definition: gaudirun.py:126
void after(CustomEventTypeRef type, const std::string &s, const StatusCode &)
Audit the end of a custom "event" for callers that do not implement INamedInterface.
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)
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)
bool isPhaseEnabled(const CustomEventTypeRef &type) const
Check if auditing is enabled for the current processing phase.
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 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:244
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.
bool isComponentEnabled(const std::string &name) const
Check if auditing is enabled for the given component.
Auditor based on the Google Heap Profiler.
std::string getDumpName(const CustomEventTypeRef &type, const std::string &name) const
bool isSequencer(INamedInterface *i) const
Check if the component in question is a GaudiSequencer or a Sequencer.