Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v31r0 (aeb156f0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
GoogleAuditor.cpp
Go to the documentation of this file.
1 
2 #include <algorithm>
3 #include <memory>
4 #include <string>
5 #include <utility>
6 #include <vector>
7 
8 #include "GaudiKernel/Auditor.h"
13 #include "GaudiKernel/MsgStream.h"
14 
16 #include "GaudiAlg/Sequencer.h"
17 
18 #include "boost/assign/list_of.hpp"
19 
20 #ifdef TCMALLOC_OLD_GOOGLE_HEADERS
21 # include "google/heap-checker.h"
22 # include "google/heap-profiler.h"
23 # include "google/profiler.h"
24 #else
25 # include "gperftools/heap-checker.h"
26 # include "gperftools/heap-profiler.h"
27 # include "gperftools/profiler.h"
28 #endif
29 
30 namespace Google {
31 
39  class AuditorBase : public extends<Auditor, IIncidentListener> {
40 
41  public:
43  using extends::extends;
44 
46  StatusCode initialize() override {
47  info() << "Initialised" << endmsg;
48 
49  // add a listener for begin event
50  auto inSvc = serviceLocator()->service<IIncidentSvc>( "IncidentSvc" );
51  if ( !inSvc ) return StatusCode::FAILURE;
52  inSvc->addListener( this, IncidentType::BeginEvent );
53 
54  // sort various lists for speed when searching
55  std::sort( m_when.begin(), m_when.end() );
56  std::sort( m_veto.begin(), m_veto.end() );
57  std::sort( m_list.begin(), m_list.end() );
58 
59  return StatusCode::SUCCESS;
60  }
61 
63  StatusCode finalize() override {
64  if ( alreadyRunning() ) stopAudit();
65  return StatusCode::SUCCESS;
66  }
67 
68  private:
70  inline void startAudit() {
71  info() << " -> Starting full audit from event " << m_nEvts << " to " << m_nEvts + m_nSampleEvents << endmsg;
72  m_inFullAudit = true;
75  t << "FULL-Events" << m_nEvts << "To" << m_nEvts + m_nSampleEvents;
76  google_before( t.str() );
77  }
78 
80  inline void stopAudit() {
81  info() << " -> Stopping full audit" << endmsg;
83  t << "FULL-Events" << m_nEvts << "To" << m_nEvts + m_nSampleEvents;
84  google_after( t.str() );
85  m_inFullAudit = false;
87  }
88 
91  inline bool isSequencer( INamedInterface* i ) const {
92  return ( dynamic_cast<GaudiSequencer*>( i ) != NULL || dynamic_cast<Sequencer*>( i ) != NULL );
93  }
94 
96  inline bool isPhaseEnabled( CustomEventTypeRef type ) const {
97  return ( std::find( m_when.begin(), m_when.end(), type ) != m_when.end() );
98  }
99 
101  inline bool isComponentEnabled( const std::string& name ) const {
102  return ( std::find( m_veto.begin(), m_veto.end(), name ) == m_veto.end() &&
103  ( m_list.empty() || std::find( m_list.begin(), m_list.end(), name ) != m_list.end() ) );
104  }
105 
106  // Construct the dump name based on processing phase and component name
107  std::string getDumpName( CustomEventTypeRef type, const std::string& name ) const {
109  t << name << "-" << type;
110  if ( type == "Execute" ) t << "-Event" << m_nEvts;
111  return t.str();
112  }
113 
114  public:
120  void handle( const Incident& incident ) override {
121  if ( IncidentType::BeginEvent == incident.type() ) {
122  ++m_nEvts;
123  m_audit = ( m_nEvts > m_eventsToSkip && ( m_freq < 0 || m_nEvts == 1 || m_nEvts % m_freq == 0 ) );
124  if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "Event " << m_nEvts << " Audit=" << m_audit << endmsg;
125  if ( m_fullEventAudit ) {
126  if ( m_inFullAudit ) {
128  stopAudit();
129  } else {
131  }
132  }
133  if ( m_audit && !m_inFullAudit && !alreadyRunning() ) { startAudit(); }
134  }
135  }
136  }
137 
138  public:
139  void before( StandardEventType type, INamedInterface* i ) override {
140  if ( !m_skipSequencers || !isSequencer( i ) ) { before( type, i->name() ); }
141  }
142 
143  void before( CustomEventTypeRef type, INamedInterface* i ) override {
144  if ( !m_skipSequencers || !isSequencer( i ) ) { before( type, i->name() ); }
145  }
146 
147  void before( StandardEventType type, const std::string& s ) override {
149  t << type;
150  before( t.str(), s );
151  }
152 
153  void before( CustomEventTypeRef type, const std::string& s ) override {
154  if ( !m_fullEventAudit && m_audit && isPhaseEnabled( type ) && isComponentEnabled( s ) ) {
155  if ( !alreadyRunning() ) {
156  info() << "Starting Auditor for " << s << ":" << type << endmsg;
157  m_startedBy = s;
158  google_before( getDumpName( type, s ) );
159  } else {
160  warning() << "Auditor already running. Cannot be started for " << s << endmsg;
161  }
162  }
163  }
164 
165  void after( StandardEventType type, INamedInterface* i, const StatusCode& sc ) override {
166  if ( !m_skipSequencers || !isSequencer( i ) ) {
168  t << type;
169  after( t.str(), i, sc );
170  }
171  }
172 
173  void after( CustomEventTypeRef type, INamedInterface* i, const StatusCode& sc ) override {
174  if ( !m_skipSequencers || !isSequencer( i ) ) { after( type, i->name(), sc ); }
175  }
176 
177  void after( StandardEventType type, const std::string& s, const StatusCode& sc ) override {
179  t << type;
180  after( t.str(), s, sc );
181  }
182 
183  void after( CustomEventTypeRef type, const std::string& s, const StatusCode& ) override {
184  if ( !m_fullEventAudit && m_audit && isPhaseEnabled( type ) && isComponentEnabled( s ) ) {
185  if ( s == m_startedBy ) { google_after( getDumpName( type, s ) ); }
186  }
187  }
188 
189  // Obsolete methods
190  void beforeInitialize( INamedInterface* i ) override { return before( IAuditor::Initialize, i ); }
191  void beforeReinitialize( INamedInterface* i ) override { return before( IAuditor::ReInitialize, i ); }
192  void beforeExecute( INamedInterface* i ) override { return before( IAuditor::Execute, i ); }
193  void beforeBeginRun( INamedInterface* i ) override { return before( IAuditor::BeginRun, i ); }
194  void beforeEndRun( INamedInterface* i ) override { return before( IAuditor::EndRun, i ); }
195  void beforeFinalize( INamedInterface* i ) override { return before( IAuditor::Finalize, i ); }
196 
197  void afterInitialize( INamedInterface* i ) override {
199  }
200  void afterReinitialize( INamedInterface* i ) override {
202  }
203  void afterExecute( INamedInterface* i, const StatusCode& s ) override { return after( IAuditor::Execute, i, s ); }
207 
208  protected:
210  virtual void google_before( const std::string& s ) = 0;
211 
213  virtual void google_after( const std::string& s ) = 0;
214 
216  virtual bool alreadyRunning() = 0;
217 
218  private:
220  this,
221  "ActivateAt",
222  {"Initialize", "ReInitialize", "Execute", "BeginRun", "EndRun", "Finalize"},
223  "List of phases to activate the Auditoring during"};
225  this, "DisableFor", {}, "List of component names to disable the auditing for"};
227  this, "EnableFor", {}, "Any component in this list will be audited. If empty, all will be done."};
228  Gaudi::Property<int> m_freq{this, "ProfileFreq", -1, "The frequence to audit events. -1 means all events"};
230  this, "DoFullEventProfile", false,
231  "If true, instead of individually auditing components, the full event (or events) will be audited in one go"};
233  this, "FullEventNSampleEvents", 1, "The number of events to include in a full event audit, if enabled"};
235  "Number of events to skip before activating the auditing"};
236  Gaudi::Property<bool> m_skipSequencers{this, "SkipSequencers", true,
237  "If true, auditing will be skipped for Sequencer objects."};
238 
239  bool m_audit = true;
240  unsigned long long m_nEvts = 0;
241  unsigned long long m_sampleEventCount =
242  0;
243  bool m_inFullAudit = false;
245  };
246 
260  class HeapProfiler : public AuditorBase {
261 
262  public:
264  using AuditorBase::AuditorBase;
265 
266  protected:
267  void google_before( const std::string& s ) override { HeapProfilerStart( s.c_str() ); }
268 
269  void google_after( const std::string& s ) override {
270  if ( m_dumpProfileHeaps ) { HeapProfilerDump( s.c_str() ); }
271  if ( m_printProfilesToLog ) {
272  const char* profile = GetHeapProfile();
273  info() << profile << endmsg;
274  delete profile;
275  }
276  HeapProfilerStop();
277  }
278 
279  bool alreadyRunning() override { return IsHeapProfilerRunning(); }
280 
281  private:
282  Gaudi::Property<bool> m_dumpProfileHeaps{this, "DumpHeapProfiles", true, ""};
283  Gaudi::Property<bool> m_printProfilesToLog{this, "PrintProfilesToLog", false, ""};
284  };
285 
299  class HeapChecker : public AuditorBase {
300 
301  public:
303  using AuditorBase::AuditorBase;
304 
305  StatusCode initialize() override {
306  const StatusCode sc = AuditorBase::initialize();
307  if ( sc.isFailure() ) return sc;
308 
309  const char* HEAPCHECK = getenv( "HEAPCHECK" );
310  if ( !HEAPCHECK ) {
311  fatal() << "Environment variable HEAPCHECK must be set to 'local'" << endmsg;
312  return StatusCode::FAILURE;
313  }
314  if ( std::string( HEAPCHECK ) != "local" ) {
315  warning() << "Environment variable HEAPCHECK is set to " << HEAPCHECK
316  << " Partial Program Heap Checking is disabled" << endmsg;
317  m_enabled = false;
318  }
319 
320  return sc;
321  }
322 
323  protected:
324  void google_before( const std::string& s ) override {
325  if ( m_enabled && !m_checker ) { m_checker.reset( new HeapLeakChecker( s.c_str() ) ); }
326  }
327 
328  void google_after( const std::string& s ) override {
329  if ( m_enabled && m_checker ) {
330  if ( !m_checker->NoLeaks() ) { warning() << "Leak detected for " << s << endmsg; }
331  m_checker.reset();
332  }
333  }
334 
335  bool alreadyRunning() override { return m_enabled && m_checker; }
336 
337  private:
338  bool m_enabled = true;
340  };
341 
355  class CPUProfiler : public AuditorBase {
356 
357  public:
358  using AuditorBase::AuditorBase;
359 
360  protected:
361  void google_before( const std::string& s ) override {
362  if ( !m_running ) {
363  m_running = true;
364  ProfilerStart( ( s + ".prof" ).c_str() );
365  }
366  }
367 
368  void google_after( const std::string& ) override {
369  if ( m_running ) {
370  ProfilerStop();
371  m_running = false;
372  }
373  }
374 
375  bool alreadyRunning() override { return m_running; }
376 
377  private:
378  bool m_running = false;
379  };
380 
384 } // namespace Google
void afterReinitialize(INamedInterface *i) override
Gaudi::Property< std::vector< std::string > > m_list
#define UNLIKELY(x)
Definition: Kernel.h:89
std::string m_startedBy
Name of the component we are currently auditing.
void beforeBeginRun(INamedInterface *i) override
void google_after(const std::string &) override
stop the google tool
void stopAudit()
stop a full event audit
Gaudi::Property< std::vector< std::string > > m_when
const std::string & type() const
Access to the incident type.
Definition: Incident.h:38
void beforeFinalize(INamedInterface *i) override
std::unique_ptr< HeapLeakChecker > m_checker
Implementation of property with value of concrete type.
Definition: Property.h:352
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
virtual void google_before(const std::string &s)=0
Start the google tool.
void google_after(const std::string &s) override
stop the google tool
bool m_audit
Internal flag to say if auditing is enabled or not for the current event.
void before(StandardEventType type, INamedInterface *i) override
void startAudit()
Start a full event audit.
void google_before(const std::string &s) override
Start the google tool.
Gaudi::Property< int > m_freq
constexpr static const auto SUCCESS
Definition: StatusCode.h:85
void handle(const Incident &incident) override
Implement the handle method for the Incident service.
Gaudi::Property< bool > m_fullEventAudit
virtual bool alreadyRunning()=0
check if we are already running the tool
StatusCode initialize() override
Initialize the auditor base.
void afterBeginRun(INamedInterface *i) override
StatusCode finalize() override
Finalize the auditor base.
bool m_inFullAudit
Internal flag to indicate if we are current in a full event audit.
bool isFailure() const
Definition: StatusCode.h:130
void google_after(const std::string &s) override
stop the google tool
unsigned long long m_sampleEventCount
Internal count of the number of events currently processed during an audit.
STL class.
#define DECLARE_COMPONENT(type)
StatusCode service(const Gaudi::Utils::TypeNameString &name, T *&svc, bool createIf=true)
Templated method to access a service by name.
Definition: ISvcLocator.h:76
void before(CustomEventTypeRef type, INamedInterface *i) override
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
unsigned long long m_nEvts
Number of events processed.
bool isPhaseEnabled(CustomEventTypeRef type) const
Check if auditing is enabled for the current processing phase.
void after(CustomEventTypeRef type, const std::string &s, const StatusCode &) override
bool alreadyRunning() override
check if we are already running the tool
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:50
SmartIF< ISvcLocator > & serviceLocator() const override
The standard service locator.
Definition: Auditor.cpp:197
void afterExecute(INamedInterface *i, const StatusCode &s) override
Auditor using the Google Heap Checker.
std::string getDumpName(CustomEventTypeRef type, const std::string &name) const
void before(CustomEventTypeRef type, const std::string &s) override
void beforeInitialize(INamedInterface *i) override
Gaudi::Property< unsigned long long > m_nSampleEvents
bool alreadyRunning() override
check if we are already running the tool
IInterface compliant class extending IInterface with the name() method.
T find(T...args)
void beforeEndRun(INamedInterface *i) override
void afterInitialize(INamedInterface *i) override
void beforeReinitialize(INamedInterface *i) override
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
Base class used to extend a class implementing other interfaces.
Definition: extends.h:10
Gaudi::Property< unsigned long long > m_eventsToSkip
void before(StandardEventType type, const std::string &s) override
void google_before(const std::string &s) override
Start the google tool.
T c_str(T...args)
Base class for all Incidents (computing events).
Definition: Incident.h:17
Gaudi::Property< bool > m_skipSequencers
string s
Definition: gaudirun.py:312
constexpr static const auto FAILURE
Definition: StatusCode.h:86
void after(StandardEventType type, const std::string &s, const StatusCode &sc) override
void google_before(const std::string &s) override
Start the google tool.
void afterFinalize(INamedInterface *i) override
StatusCode initialize() override
Initialize the auditor base.
T sort(T...args)
Base for Google Auditors.
MsgStream & fatal() const
shortcut for the method msgStream(MSG::FATAL)
void beforeExecute(INamedInterface *i) override
virtual void google_after(const std::string &s)=0
stop the google tool
void after(CustomEventTypeRef type, INamedInterface *i, const StatusCode &sc) override
Auditor using the Google CPU Profiler.
bool alreadyRunning() override
check if we are already running the tool
const std::string & name() const override
Definition: Auditor.cpp:193
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:192
virtual const std::string & name() const =0
Retrieve the name of the instance.
The interface implemented by the IncidentSvc service.
Definition: IIncidentSvc.h:23
void after(StandardEventType type, INamedInterface *i, const StatusCode &sc) override
bool isComponentEnabled(const std::string &name) const
Check if auditing is enabled for the given component.
Auditor based on the Google Heap Profiler.
void afterEndRun(INamedInterface *i) override
bool isSequencer(INamedInterface *i) const
Check if the component in question is a GaudiSequencer or a Sequencer.
MSG::Level msgLevel() const
get the cached level (originally extracted from the embedded MsgStream)
Gaudi::Property< std::vector< std::string > > m_veto