The Gaudi Framework  v32r2 (46d42edc)
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 #ifdef TCMALLOC_OLD_GOOGLE_HEADERS
19 # include "google/heap-checker.h"
20 # include "google/heap-profiler.h"
21 # include "google/profiler.h"
22 #else
23 # include "gperftools/heap-checker.h"
24 # include "gperftools/heap-profiler.h"
25 # include "gperftools/profiler.h"
26 #endif
27 
28 namespace Google {
29 
37  class AuditorBase : public extends<Auditor, IIncidentListener> {
38 
39  public:
41  using extends::extends;
42 
44  StatusCode initialize() override {
45  info() << "Initialised" << endmsg;
46 
47  // add a listener for begin event
48  auto inSvc = serviceLocator()->service<IIncidentSvc>( "IncidentSvc" );
49  if ( !inSvc ) return StatusCode::FAILURE;
50  inSvc->addListener( this, IncidentType::BeginEvent );
51 
52  // sort various lists for speed when searching
53  std::sort( m_when.begin(), m_when.end() );
54  std::sort( m_veto.begin(), m_veto.end() );
55  std::sort( m_list.begin(), m_list.end() );
56 
57  return StatusCode::SUCCESS;
58  }
59 
61  StatusCode finalize() override {
62  if ( alreadyRunning() ) stopAudit();
63  return StatusCode::SUCCESS;
64  }
65 
66  private:
68  inline void startAudit() {
69  info() << " -> Starting full audit from event " << m_nEvts << " to " << m_nEvts + m_nSampleEvents << endmsg;
70  m_inFullAudit = true;
73  t << "FULL-Events" << m_nEvts << "To" << m_nEvts + m_nSampleEvents;
74  google_before( t.str() );
75  }
76 
78  inline void stopAudit() {
79  info() << " -> Stopping full audit" << endmsg;
81  t << "FULL-Events" << m_nEvts << "To" << m_nEvts + m_nSampleEvents;
82  google_after( t.str() );
83  m_inFullAudit = false;
85  }
86 
89  inline bool isSequencer( INamedInterface* i ) const {
90  return ( dynamic_cast<GaudiSequencer*>( i ) != NULL || dynamic_cast<Sequencer*>( i ) != NULL );
91  }
92 
94  inline bool isPhaseEnabled( CustomEventTypeRef type ) const {
95  return ( std::find( m_when.begin(), m_when.end(), type ) != m_when.end() );
96  }
97 
99  inline bool isComponentEnabled( const std::string& name ) const {
100  return ( std::find( m_veto.begin(), m_veto.end(), name ) == m_veto.end() &&
101  ( m_list.empty() || std::find( m_list.begin(), m_list.end(), name ) != m_list.end() ) );
102  }
103 
104  // Construct the dump name based on processing phase and component name
105  std::string getDumpName( CustomEventTypeRef type, const std::string& name ) const {
107  t << name << "-" << type;
108  if ( type == "Execute" ) t << "-Event" << m_nEvts;
109  return t.str();
110  }
111 
112  public:
118  void handle( const Incident& incident ) override {
119  if ( IncidentType::BeginEvent == incident.type() ) {
120  ++m_nEvts;
121  m_audit = ( m_nEvts > m_eventsToSkip && ( m_freq < 0 || m_nEvts == 1 || m_nEvts % m_freq == 0 ) );
122  if ( UNLIKELY( msgLevel( MSG::DEBUG ) ) ) debug() << "Event " << m_nEvts << " Audit=" << m_audit << endmsg;
123  if ( m_fullEventAudit ) {
124  if ( m_inFullAudit ) {
126  stopAudit();
127  } else {
129  }
130  }
131  if ( m_audit && !m_inFullAudit && !alreadyRunning() ) { startAudit(); }
132  }
133  }
134  }
135 
136  public:
137  void before( StandardEventType type, INamedInterface* i ) override {
138  if ( !m_skipSequencers || !isSequencer( i ) ) { before( type, i->name() ); }
139  }
140 
141  void before( CustomEventTypeRef type, INamedInterface* i ) override {
142  if ( !m_skipSequencers || !isSequencer( i ) ) { before( type, i->name() ); }
143  }
144 
145  void before( StandardEventType type, const std::string& s ) override {
147  t << type;
148  before( t.str(), s );
149  }
150 
151  void before( CustomEventTypeRef type, const std::string& s ) override {
153  if ( !alreadyRunning() ) {
154  info() << "Starting Auditor for " << s << ":" << type << endmsg;
155  m_startedBy = s;
157  } else {
158  warning() << "Auditor already running. Cannot be started for " << s << endmsg;
159  }
160  }
161  }
162 
163  void after( StandardEventType type, INamedInterface* i, const StatusCode& sc ) override {
164  if ( !m_skipSequencers || !isSequencer( i ) ) {
166  t << type;
167  after( t.str(), i, sc );
168  }
169  }
170 
171  void after( CustomEventTypeRef type, INamedInterface* i, const StatusCode& sc ) override {
172  if ( !m_skipSequencers || !isSequencer( i ) ) { after( type, i->name(), sc ); }
173  }
174 
175  void after( StandardEventType type, const std::string& s, const StatusCode& sc ) override {
177  t << type;
178  after( t.str(), s, sc );
179  }
180 
181  void after( CustomEventTypeRef type, const std::string& s, const StatusCode& ) override {
183  if ( s == m_startedBy ) { google_after( getDumpName( type, s ) ); }
184  }
185  }
186 
187  // Obsolete methods
188  void beforeInitialize( INamedInterface* i ) override { return before( IAuditor::Initialize, i ); }
189  void beforeReinitialize( INamedInterface* i ) override { return before( IAuditor::ReInitialize, i ); }
190  void beforeExecute( INamedInterface* i ) override { return before( IAuditor::Execute, i ); }
191  void beforeBeginRun( INamedInterface* i ) override { return before( IAuditor::BeginRun, i ); }
192  void beforeEndRun( INamedInterface* i ) override { return before( IAuditor::EndRun, i ); }
193  void beforeFinalize( INamedInterface* i ) override { return before( IAuditor::Finalize, i ); }
194 
195  void afterInitialize( INamedInterface* i ) override {
197  }
198  void afterReinitialize( INamedInterface* i ) override {
200  }
201  void afterExecute( INamedInterface* i, const StatusCode& s ) override { return after( IAuditor::Execute, i, s ); }
205 
206  protected:
208  virtual void google_before( const std::string& s ) = 0;
209 
211  virtual void google_after( const std::string& s ) = 0;
212 
214  virtual bool alreadyRunning() = 0;
215 
216  private:
218  this,
219  "ActivateAt",
220  {"Initialize", "ReInitialize", "Execute", "BeginRun", "EndRun", "Finalize"},
221  "List of phases to activate the Auditoring during"};
223  this, "DisableFor", {}, "List of component names to disable the auditing for"};
225  this, "EnableFor", {}, "Any component in this list will be audited. If empty, all will be done."};
226  Gaudi::Property<int> m_freq{this, "ProfileFreq", -1, "The frequence to audit events. -1 means all events"};
228  this, "DoFullEventProfile", false,
229  "If true, instead of individually auditing components, the full event (or events) will be audited in one go"};
231  this, "FullEventNSampleEvents", 1, "The number of events to include in a full event audit, if enabled"};
233  "Number of events to skip before activating the auditing"};
234  Gaudi::Property<bool> m_skipSequencers{this, "SkipSequencers", true,
235  "If true, auditing will be skipped for Sequencer objects."};
236 
237  bool m_audit = true;
238  unsigned long long m_nEvts = 0;
239  unsigned long long m_sampleEventCount =
240  0;
241  bool m_inFullAudit = false;
243  };
244 
258  class HeapProfiler : public AuditorBase {
259 
260  public:
262  using AuditorBase::AuditorBase;
263 
264  protected:
265  void google_before( const std::string& s ) override { HeapProfilerStart( s.c_str() ); }
266 
267  void google_after( const std::string& s ) override {
268  if ( m_dumpProfileHeaps ) { HeapProfilerDump( s.c_str() ); }
269  if ( m_printProfilesToLog ) {
270  const char* profile = GetHeapProfile();
271  info() << profile << endmsg;
272  delete profile;
273  }
274  HeapProfilerStop();
275  }
276 
277  bool alreadyRunning() override { return IsHeapProfilerRunning(); }
278 
279  private:
280  Gaudi::Property<bool> m_dumpProfileHeaps{this, "DumpHeapProfiles", true, ""};
281  Gaudi::Property<bool> m_printProfilesToLog{this, "PrintProfilesToLog", false, ""};
282  };
283 
297  class HeapChecker : public AuditorBase {
298 
299  public:
301  using AuditorBase::AuditorBase;
302 
303  StatusCode initialize() override {
304  const StatusCode sc = AuditorBase::initialize();
305  if ( sc.isFailure() ) return sc;
306 
307  const char* HEAPCHECK = getenv( "HEAPCHECK" );
308  if ( !HEAPCHECK ) {
309  fatal() << "Environment variable HEAPCHECK must be set to 'local'" << endmsg;
310  return StatusCode::FAILURE;
311  }
312  if ( std::string( HEAPCHECK ) != "local" ) {
313  warning() << "Environment variable HEAPCHECK is set to " << HEAPCHECK
314  << " Partial Program Heap Checking is disabled" << endmsg;
315  m_enabled = false;
316  }
317 
318  return sc;
319  }
320 
321  protected:
322  void google_before( const std::string& s ) override {
323  if ( m_enabled && !m_checker ) { m_checker.reset( new HeapLeakChecker( s.c_str() ) ); }
324  }
325 
326  void google_after( const std::string& s ) override {
327  if ( m_enabled && m_checker ) {
328  if ( !m_checker->NoLeaks() ) { warning() << "Leak detected for " << s << endmsg; }
329  m_checker.reset();
330  }
331  }
332 
333  bool alreadyRunning() override { return m_enabled && m_checker; }
334 
335  private:
336  bool m_enabled = true;
338  };
339 
353  class CPUProfiler : public AuditorBase {
354 
355  public:
356  using AuditorBase::AuditorBase;
357 
358  protected:
359  void google_before( const std::string& s ) override {
360  if ( !m_running ) {
361  m_running = true;
362  ProfilerStart( ( s + ".prof" ).c_str() );
363  }
364  }
365 
366  void google_after( const std::string& ) override {
367  if ( m_running ) {
368  ProfilerStop();
369  m_running = false;
370  }
371  }
372 
373  bool alreadyRunning() override { return m_running; }
374 
375  private:
376  bool m_running = false;
377  };
378 
382 } // namespace Google
void afterReinitialize(INamedInterface *i) override
Gaudi::Property< std::vector< std::string > > m_list
#define UNLIKELY(x)
Definition: Kernel.h:96
bool isPhaseEnabled(CustomEventTypeRef type) const
Check if auditing is enabled for the current processing phase.
std::string m_startedBy
Name of the component we are currently auditing.
std::string getDumpName(CustomEventTypeRef type, const std::string &name) const
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
void beforeFinalize(INamedInterface *i) override
std::unique_ptr< HeapLeakChecker > m_checker
Implementation of property with value of concrete type.
Definition: Property.h:352
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
virtual void google_before(const std::string &s)=0
Start the google tool.
const std::string & type() const
Access to the incident type.
Definition: Incident.h:38
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.
bool isSequencer(INamedInterface *i) const
Check if the component in question is a GaudiSequencer or a Sequencer.
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< bool > m_dumpProfileHeaps
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.
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
SmartIF< ISvcLocator > & serviceLocator() const override
The standard service locator.
Definition: Auditor.cpp:197
bool m_inFullAudit
Internal flag to indicate if we are current in a full event audit.
void google_after(const std::string &s) override
stop the google tool
Gaudi::Property< bool > m_printProfilesToLog
unsigned long long m_sampleEventCount
Internal count of the number of events currently processed during an audit.
MSG::Level msgLevel() const
get the cached level (originally extracted from the embedded MsgStream)
virtual const std::string & name() const =0
Retrieve the name of the instance.
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
unsigned long long m_nEvts
Number of events processed.
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
void afterExecute(INamedInterface *i, const StatusCode &s) override
Auditor using the Google Heap Checker.
void before(CustomEventTypeRef type, const std::string &s) override
T str(T... args)
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
void beforeInitialize(INamedInterface *i) override
T reset(T... args)
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
Base class used to extend a class implementing other interfaces.
Definition: extends.h:10
Gaudi::Property< unsigned long long > m_eventsToSkip
bool isComponentEnabled(const std::string &name) const
Check if auditing is enabled for the given component.
void before(StandardEventType type, const std::string &s) override
void google_before(const std::string &s) override
Start the google tool.
Base class for all Incidents (computing events).
Definition: Incident.h:17
Gaudi::Property< bool > m_skipSequencers
const std::string & name() const override
Definition: Auditor.cpp:193
string s
Definition: gaudirun.py:318
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)
bool isFailure() const
Definition: StatusCode.h:130
Base for Google Auditors.
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
MsgStream & fatal() const
shortcut for the method msgStream(MSG::FATAL)
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:192
The interface implemented by the IncidentSvc service.
Definition: IIncidentSvc.h:23
void after(StandardEventType type, INamedInterface *i, const StatusCode &sc) override
Auditor based on the Google Heap Profiler.
void afterEndRun(INamedInterface *i) override
Gaudi::Property< std::vector< std::string > > m_veto