Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v36r16 (ea80daf8)
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 * (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
3 * *
4 * This software is distributed under the terms of the Apache version 2 licence, *
5 * copied verbatim in the file "LICENSE". *
6 * *
7 * In applying this licence, CERN does not waive the privileges and immunities *
8 * granted to it by virtue of its status as an Intergovernmental Organization *
9 * or submit itself to any jurisdiction. *
10 \***********************************************************************************/
11 
12 #include <algorithm>
13 #include <memory>
14 #include <string>
15 #include <utility>
16 #include <vector>
17 
18 #include "GaudiKernel/Auditor.h"
23 #include "GaudiKernel/MsgStream.h"
24 
26 #include "GaudiAlg/Sequencer.h"
27 
28 #ifdef TCMALLOC_OLD_GOOGLE_HEADERS
29 # include "google/heap-checker.h"
30 # include "google/heap-profiler.h"
31 # include "google/profiler.h"
32 #else
33 # include "gperftools/heap-checker.h"
34 # include "gperftools/heap-profiler.h"
35 # include "gperftools/profiler.h"
36 #endif
37 
38 namespace Google {
39 
47  class AuditorBase : public extends<Auditor, IIncidentListener> {
48 
49  public:
51  using extends::extends;
52 
54  StatusCode initialize() override {
55  info() << "Initialised" << endmsg;
56 
57  // add a listener for begin event
58  auto inSvc = serviceLocator()->service<IIncidentSvc>( "IncidentSvc" );
59  if ( !inSvc ) return StatusCode::FAILURE;
60  inSvc->addListener( this, IncidentType::BeginEvent );
61 
62  // sort various lists for speed when searching
63  std::sort( m_when.begin(), m_when.end() );
64  std::sort( m_veto.begin(), m_veto.end() );
65  std::sort( m_list.begin(), m_list.end() );
66 
67  return StatusCode::SUCCESS;
68  }
69 
71  StatusCode finalize() override {
72  if ( alreadyRunning() ) stopAudit();
73  return StatusCode::SUCCESS;
74  }
75 
76  private:
78  inline void startAudit() {
79  info() << " -> Starting full audit from event " << m_nEvts << " to " << m_nEvts + m_nSampleEvents << endmsg;
80  m_inFullAudit = true;
83  t << "FULL-Events" << m_nEvts << "To" << m_nEvts + m_nSampleEvents;
84  google_before( t.str() );
85  }
86 
88  inline void stopAudit() {
89  info() << " -> Stopping full audit" << endmsg;
91  t << "FULL-Events" << m_nEvts << "To" << m_nEvts + m_nSampleEvents;
92  google_after( t.str() );
93  m_inFullAudit = false;
95  }
96 
99  inline bool isSequencer( INamedInterface* i ) const {
100  return ( dynamic_cast<GaudiSequencer*>( i ) != NULL || dynamic_cast<Sequencer*>( i ) != NULL );
101  }
102 
104  inline bool isPhaseEnabled( CustomEventTypeRef type ) const {
105  return ( std::find( m_when.begin(), m_when.end(), type ) != m_when.end() );
106  }
107 
109  inline bool isComponentEnabled( std::string_view name ) const {
110  return ( std::find( m_veto.begin(), m_veto.end(), name ) == m_veto.end() &&
111  ( m_list.empty() || std::find( m_list.begin(), m_list.end(), name ) != m_list.end() ) );
112  }
113 
114  // Construct the dump name based on processing phase and component name
115  std::string getDumpName( CustomEventTypeRef type, std::string_view name ) const {
117  t << name << "-" << type;
118  if ( type == "Execute" ) t << "-Event" << m_nEvts;
119  return t.str();
120  }
121 
122  public:
128  void handle( const Incident& incident ) override {
129  if ( IncidentType::BeginEvent == incident.type() ) {
130  ++m_nEvts;
131  m_audit = ( m_nEvts > m_eventsToSkip && ( m_freq < 0 || m_nEvts == 1 || m_nEvts % m_freq == 0 ) );
132  if ( msgLevel( MSG::DEBUG ) ) debug() << "Event " << m_nEvts << " Audit=" << m_audit << endmsg;
133  if ( m_fullEventAudit ) {
134  if ( m_inFullAudit ) {
136  stopAudit();
137  } else {
139  }
140  }
141  if ( m_audit && !m_inFullAudit && !alreadyRunning() ) { startAudit(); }
142  }
143  }
144  }
145 
146  public:
147  void before( StandardEventType type, INamedInterface* i ) override {
148  if ( !m_skipSequencers || !isSequencer( i ) ) { before( type, i->name() ); }
149  }
150 
151  void before( CustomEventTypeRef type, INamedInterface* i ) override {
152  if ( !m_skipSequencers || !isSequencer( i ) ) { before( type, i->name() ); }
153  }
154 
155  void before( StandardEventType type, const std::string& s ) override {
157  t << type;
158  before( t.str(), s );
159  }
160 
161  void before( CustomEventTypeRef type, const std::string& s ) override {
163  if ( !alreadyRunning() ) {
164  info() << "Starting Auditor for " << s << ":" << type << endmsg;
165  m_startedBy = s;
167  } else {
168  warning() << "Auditor already running. Cannot be started for " << s << endmsg;
169  }
170  }
171  }
172 
173  void after( StandardEventType type, INamedInterface* i, const StatusCode& sc ) override {
174  if ( !m_skipSequencers || !isSequencer( i ) ) {
176  t << type;
177  after( t.str(), i, sc );
178  }
179  }
180 
181  void after( CustomEventTypeRef type, INamedInterface* i, const StatusCode& sc ) override {
182  if ( !m_skipSequencers || !isSequencer( i ) ) { after( type, i->name(), sc ); }
183  }
184 
185  void after( StandardEventType type, const std::string& s, const StatusCode& sc ) override {
187  t << type;
188  after( t.str(), s, sc );
189  }
190 
191  void after( CustomEventTypeRef type, const std::string& s, const StatusCode& ) override {
193  if ( s == m_startedBy ) { google_after( getDumpName( type, s ) ); }
194  }
195  }
196 
197  // Obsolete methods
198  void beforeInitialize( INamedInterface* i ) override { return before( IAuditor::Initialize, i ); }
199  void beforeReinitialize( INamedInterface* i ) override { return before( IAuditor::ReInitialize, i ); }
200  void beforeExecute( INamedInterface* i ) override { return before( IAuditor::Execute, i ); }
201  void beforeFinalize( INamedInterface* i ) override { return before( IAuditor::Finalize, i ); }
202 
203  void afterInitialize( INamedInterface* i ) override {
205  }
206  void afterReinitialize( INamedInterface* i ) override {
208  }
209  void afterExecute( INamedInterface* i, const StatusCode& s ) override { return after( IAuditor::Execute, i, s ); }
211 
212  protected:
214  virtual void google_before( const std::string& s ) = 0;
215 
217  virtual void google_after( const std::string& s ) = 0;
218 
220  virtual bool alreadyRunning() = 0;
221 
222  private:
224  "ActivateAt",
225  { "Initialize", "ReInitialize", "Execute", "Finalize" },
226  "List of phases to activate the Auditoring during" };
228  this, "DisableFor", {}, "List of component names to disable the auditing for" };
230  this, "EnableFor", {}, "Any component in this list will be audited. If empty, all will be done." };
231  Gaudi::Property<int> m_freq{ this, "ProfileFreq", -1, "The frequence to audit events. -1 means all events" };
233  this, "DoFullEventProfile", false,
234  "If true, instead of individually auditing components, the full event (or events) will be audited in one go" };
236  this, "FullEventNSampleEvents", 1, "The number of events to include in a full event audit, if enabled" };
238  "Number of events to skip before activating the auditing" };
239  Gaudi::Property<bool> m_skipSequencers{ this, "SkipSequencers", true,
240  "If true, auditing will be skipped for Sequencer objects." };
241 
242  bool m_audit = true;
243  unsigned long long m_nEvts = 0;
244  unsigned long long m_sampleEventCount =
245  0;
246  bool m_inFullAudit = false;
248  };
249 
263  class HeapProfiler : public AuditorBase {
264 
265  public:
267  using AuditorBase::AuditorBase;
268 
269  protected:
270  void google_before( const std::string& s ) override { HeapProfilerStart( s.c_str() ); }
271 
272  void google_after( const std::string& s ) override {
273  if ( m_dumpProfileHeaps ) { HeapProfilerDump( s.c_str() ); }
274  if ( m_printProfilesToLog ) {
275  const char* profile = GetHeapProfile();
276  info() << profile << endmsg;
277  delete profile;
278  }
279  HeapProfilerStop();
280  }
281 
282  bool alreadyRunning() override { return IsHeapProfilerRunning(); }
283 
284  private:
285  Gaudi::Property<bool> m_dumpProfileHeaps{ this, "DumpHeapProfiles", true, "" };
286  Gaudi::Property<bool> m_printProfilesToLog{ this, "PrintProfilesToLog", false, "" };
287  };
288 
302  class HeapChecker : public AuditorBase {
303 
304  public:
306  using AuditorBase::AuditorBase;
307 
308  StatusCode initialize() override {
309  const StatusCode sc = AuditorBase::initialize();
310  if ( sc.isFailure() ) return sc;
311 
312  const char* HEAPCHECK = getenv( "HEAPCHECK" );
313  if ( !HEAPCHECK ) {
314  fatal() << "Environment variable HEAPCHECK must be set to 'local'" << endmsg;
315  return StatusCode::FAILURE;
316  }
317  if ( std::string( HEAPCHECK ) != "local" ) {
318  warning() << "Environment variable HEAPCHECK is set to " << HEAPCHECK
319  << " Partial Program Heap Checking is disabled" << endmsg;
320  m_enabled = false;
321  }
322 
323  return sc;
324  }
325 
326  protected:
327  void google_before( const std::string& s ) override {
328  if ( m_enabled && !m_checker ) { m_checker.reset( new HeapLeakChecker( s.c_str() ) ); }
329  }
330 
331  void google_after( const std::string& s ) override {
332  if ( m_enabled && m_checker ) {
333  if ( !m_checker->NoLeaks() ) { warning() << "Leak detected for " << s << endmsg; }
334  m_checker.reset();
335  }
336  }
337 
338  bool alreadyRunning() override { return m_enabled && m_checker; }
339 
340  private:
341  bool m_enabled = true;
343  };
344 
358  class CPUProfiler : public AuditorBase {
359 
360  public:
361  using AuditorBase::AuditorBase;
362 
363  protected:
364  void google_before( const std::string& s ) override {
365  if ( !m_running ) {
366  m_running = true;
367  ProfilerStart( ( s + ".prof" ).c_str() );
368  }
369  }
370 
371  void google_after( const std::string& ) override {
372  if ( m_running ) {
373  ProfilerStop();
374  m_running = false;
375  }
376  }
377 
378  bool alreadyRunning() override { return m_running; }
379 
380  private:
381  bool m_running = false;
382  };
383 
387 } // namespace Google
Google::AuditorBase::after
void after(CustomEventTypeRef type, const std::string &s, const StatusCode &) override
Definition: GoogleAuditor.cpp:191
MSG::DEBUG
@ DEBUG
Definition: IMessageSvc.h:25
Google::AuditorBase::before
void before(CustomEventTypeRef type, const std::string &s) override
Definition: GoogleAuditor.cpp:161
Google::HeapProfiler::google_before
void google_before(const std::string &s) override
Start the google tool.
Definition: GoogleAuditor.cpp:270
Google::AuditorBase::m_freq
Gaudi::Property< int > m_freq
Definition: GoogleAuditor.cpp:231
std::string
STL class.
Sequencer
ClassName: Sequencer.
Definition: Sequencer.h:35
IAuditor::Execute
@ Execute
Definition: IAuditor.h:34
Google::HeapProfiler::m_dumpProfileHeaps
Gaudi::Property< bool > m_dumpProfileHeaps
Definition: GoogleAuditor.cpp:285
GaudiException.h
gaudirun.s
string s
Definition: gaudirun.py:348
std::find
T find(T... args)
Google::AuditorBase::after
void after(StandardEventType type, INamedInterface *i, const StatusCode &sc) override
Definition: GoogleAuditor.cpp:173
Google::AuditorBase::m_inFullAudit
bool m_inFullAudit
Internal flag to indicate if we are current in a full event audit.
Definition: GoogleAuditor.cpp:246
Google::HeapChecker::alreadyRunning
bool alreadyRunning() override
check if we are already running the tool
Definition: GoogleAuditor.cpp:338
INamedInterface::name
virtual const std::string & name() const =0
Retrieve the name of the instance.
Google::AuditorBase::before
void before(CustomEventTypeRef type, INamedInterface *i) override
Definition: GoogleAuditor.cpp:151
Google::AuditorBase::isPhaseEnabled
bool isPhaseEnabled(CustomEventTypeRef type) const
Check if auditing is enabled for the current processing phase.
Definition: GoogleAuditor.cpp:104
Google::AuditorBase::initialize
StatusCode initialize() override
Initialize the auditor base.
Definition: GoogleAuditor.cpp:54
Google::AuditorBase::m_skipSequencers
Gaudi::Property< bool > m_skipSequencers
Definition: GoogleAuditor.cpp:239
Google::AuditorBase::google_before
virtual void google_before(const std::string &s)=0
Start the google tool.
Google::AuditorBase::beforeExecute
void beforeExecute(INamedInterface *i) override
Definition: GoogleAuditor.cpp:200
std::sort
T sort(T... args)
std::unique_ptr::reset
T reset(T... args)
CommonMessaging< implements< IAuditor, IProperty > >::msgLevel
MSG::Level msgLevel() const
get the cached level (originally extracted from the embedded MsgStream)
Definition: CommonMessaging.h:148
IAuditorSvc.h
Google::AuditorBase::beforeInitialize
void beforeInitialize(INamedInterface *i) override
Definition: GoogleAuditor.cpp:198
IIncidentSvc.h
Google::HeapChecker::google_before
void google_before(const std::string &s) override
Start the google tool.
Definition: GoogleAuditor.cpp:327
Google::AuditorBase::isSequencer
bool isSequencer(INamedInterface *i) const
Check if the component in question is a GaudiSequencer or a Sequencer.
Definition: GoogleAuditor.cpp:99
Google::AuditorBase::afterFinalize
void afterFinalize(INamedInterface *i) override
Definition: GoogleAuditor.cpp:210
Auditor::name
const std::string & name() const override
Definition: Auditor.cpp:192
IAuditor::Finalize
@ Finalize
Definition: IAuditor.h:34
bug_34121.t
t
Definition: bug_34121.py:30
Google::CPUProfiler::m_running
bool m_running
Definition: GoogleAuditor.cpp:381
Google::AuditorBase::after
void after(CustomEventTypeRef type, INamedInterface *i, const StatusCode &sc) override
Definition: GoogleAuditor.cpp:181
Google::AuditorBase::afterReinitialize
void afterReinitialize(INamedInterface *i) override
Definition: GoogleAuditor.cpp:206
StatusCode
Definition: StatusCode.h:65
Google::AuditorBase::handle
void handle(const Incident &incident) override
Implement the handle method for the Incident service.
Definition: GoogleAuditor.cpp:128
Google::AuditorBase::getDumpName
std::string getDumpName(CustomEventTypeRef type, std::string_view name) const
Definition: GoogleAuditor.cpp:115
Google::HeapProfiler
Definition: GoogleAuditor.cpp:263
Google::CPUProfiler
Definition: GoogleAuditor.cpp:358
Google::AuditorBase::alreadyRunning
virtual bool alreadyRunning()=0
check if we are already running the tool
Google::AuditorBase::m_veto
Gaudi::Property< std::vector< std::string > > m_veto
Definition: GoogleAuditor.cpp:227
IAuditor::Initialize
@ Initialize
Definition: IAuditor.h:34
IAuditor::ReInitialize
@ ReInitialize
Definition: IAuditor.h:34
Google::AuditorBase::m_list
Gaudi::Property< std::vector< std::string > > m_list
Definition: GoogleAuditor.cpp:229
Google::AuditorBase::isComponentEnabled
bool isComponentEnabled(std::string_view name) const
Check if auditing is enabled for the given component.
Definition: GoogleAuditor.cpp:109
Google::AuditorBase::m_eventsToSkip
Gaudi::Property< unsigned long long > m_eventsToSkip
Definition: GoogleAuditor.cpp:237
Google::AuditorBase::afterInitialize
void afterInitialize(INamedInterface *i) override
Definition: GoogleAuditor.cpp:203
Google::AuditorBase::stopAudit
void stopAudit()
stop a full event audit
Definition: GoogleAuditor.cpp:88
Google::CPUProfiler::google_after
void google_after(const std::string &) override
stop the google tool
Definition: GoogleAuditor.cpp:371
Google::AuditorBase::before
void before(StandardEventType type, const std::string &s) override
Definition: GoogleAuditor.cpp:155
Google::AuditorBase::after
void after(StandardEventType type, const std::string &s, const StatusCode &sc) override
Definition: GoogleAuditor.cpp:185
Google::HeapChecker::m_checker
std::unique_ptr< HeapLeakChecker > m_checker
Definition: GoogleAuditor.cpp:342
Google::HeapChecker
Definition: GoogleAuditor.cpp:302
Google::AuditorBase::m_audit
bool m_audit
Internal flag to say if auditing is enabled or not for the current event.
Definition: GoogleAuditor.cpp:242
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:203
extends
Base class used to extend a class implementing other interfaces.
Definition: extends.h:20
Google::HeapChecker::m_enabled
bool m_enabled
Definition: GoogleAuditor.cpp:341
Google::AuditorBase::m_when
Gaudi::Property< std::vector< std::string > > m_when
Definition: GoogleAuditor.cpp:223
Google::AuditorBase::m_nEvts
unsigned long long m_nEvts
Number of events processed.
Definition: GoogleAuditor.cpp:243
Google::HeapChecker::google_after
void google_after(const std::string &s) override
stop the google tool
Definition: GoogleAuditor.cpp:331
std::ostringstream
STL class.
StatusCode::isFailure
bool isFailure() const
Definition: StatusCode.h:129
Google::AuditorBase::afterExecute
void afterExecute(INamedInterface *i, const StatusCode &s) override
Definition: GoogleAuditor.cpp:209
Google::AuditorBase::google_after
virtual void google_after(const std::string &s)=0
stop the google tool
gaudirun.type
type
Definition: gaudirun.py:162
INamedInterface
Definition: INamedInterface.h:25
GaudiSequencer
Definition: GaudiSequencer.h:38
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
Google::AuditorBase::startAudit
void startAudit()
Start a full event audit.
Definition: GoogleAuditor.cpp:78
Google::AuditorBase::m_nSampleEvents
Gaudi::Property< unsigned long long > m_nSampleEvents
Definition: GoogleAuditor.cpp:235
Google::CPUProfiler::alreadyRunning
bool alreadyRunning() override
check if we are already running the tool
Definition: GoogleAuditor.cpp:378
Google::HeapChecker::initialize
StatusCode initialize() override
Initialize the auditor base.
Definition: GoogleAuditor.cpp:308
IIncidentListener.h
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginServiceV1.h:46
Google::HeapProfiler::m_printProfilesToLog
Gaudi::Property< bool > m_printProfilesToLog
Definition: GoogleAuditor.cpp:286
Google::AuditorBase::finalize
StatusCode finalize() override
Finalize the auditor base.
Definition: GoogleAuditor.cpp:71
Google::AuditorBase::m_fullEventAudit
Gaudi::Property< bool > m_fullEventAudit
Definition: GoogleAuditor.cpp:232
Google::AuditorBase::m_sampleEventCount
unsigned long long m_sampleEventCount
Internal count of the number of events currently processed during an audit.
Definition: GoogleAuditor.cpp:244
Incident::type
const std::string & type() const
Access to the incident type.
Definition: Incident.h:48
Google::AuditorBase::m_startedBy
std::string m_startedBy
Name of the component we are currently auditing.
Definition: GoogleAuditor.cpp:247
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:101
Google::AuditorBase
Definition: GoogleAuditor.cpp:47
GaudiSequencer.h
IIncidentSvc
Definition: IIncidentSvc.h:33
Google::AuditorBase::beforeReinitialize
void beforeReinitialize(INamedInterface *i) override
Definition: GoogleAuditor.cpp:199
Google::AuditorBase::beforeFinalize
void beforeFinalize(INamedInterface *i) override
Definition: GoogleAuditor.cpp:201
Incident
Definition: Incident.h:27
std::unique_ptr< HeapLeakChecker >
Auditor::serviceLocator
SmartIF< ISvcLocator > & serviceLocator() const override
The standard service locator.
Definition: Auditor.cpp:196
Google
Definition: GoogleAuditor.cpp:38
Gaudi::Property
Implementation of property with value of concrete type.
Definition: Property.h:39
Google::HeapProfiler::google_after
void google_after(const std::string &s) override
stop the google tool
Definition: GoogleAuditor.cpp:272
Google::CPUProfiler::google_before
void google_before(const std::string &s) override
Start the google tool.
Definition: GoogleAuditor.cpp:364
MsgStream.h
Sequencer.h
Google::AuditorBase::before
void before(StandardEventType type, INamedInterface *i) override
Definition: GoogleAuditor.cpp:147
Auditor.h
Google::HeapProfiler::alreadyRunning
bool alreadyRunning() override
check if we are already running the tool
Definition: GoogleAuditor.cpp:282