The Gaudi Framework  master (37c0b60a)
GoogleAuditor.cpp
Go to the documentation of this file.
1 /***********************************************************************************\
2 * (c) Copyright 1998-2023 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 <GaudiKernel/Auditor.h>
14 #include <GaudiKernel/IAlgorithm.h>
18 #include <GaudiKernel/MsgStream.h>
19 #include <algorithm>
20 #include <gperftools/heap-checker.h>
21 #include <gperftools/heap-profiler.h>
22 #include <gperftools/profiler.h>
23 #include <memory>
24 #include <string>
25 #include <utility>
26 #include <vector>
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 
87  // Check if the component in question is a Sequencer
88  inline bool isSequencer( INamedInterface* i ) const {
89  if ( auto alg = dynamic_cast<IAlgorithm*>( i ) ) { return alg->isSequence(); }
90  return false;
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( std::string_view 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, std::string_view 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 ( 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 beforeFinalize( INamedInterface* i ) override { return before( IAuditor::Finalize, i ); }
192 
193  void afterInitialize( INamedInterface* i ) override {
195  }
196  void afterReinitialize( INamedInterface* i ) override {
198  }
199  void afterExecute( INamedInterface* i, const StatusCode& s ) override { return after( IAuditor::Execute, i, s ); }
201 
202  protected:
204  virtual void google_before( const std::string& s ) = 0;
205 
207  virtual void google_after( const std::string& s ) = 0;
208 
210  virtual bool alreadyRunning() = 0;
211 
212  private:
214  "ActivateAt",
215  { "Initialize", "ReInitialize", "Execute", "Finalize" },
216  "List of phases to activate the Auditoring during" };
218  this, "DisableFor", {}, "List of component names to disable the auditing for" };
220  this, "EnableFor", {}, "Any component in this list will be audited. If empty, all will be done." };
221  Gaudi::Property<int> m_freq{ this, "ProfileFreq", -1, "The frequence to audit events. -1 means all events" };
223  this, "DoFullEventProfile", false,
224  "If true, instead of individually auditing components, the full event (or events) will be audited in one go" };
226  this, "FullEventNSampleEvents", 1, "The number of events to include in a full event audit, if enabled" };
228  "Number of events to skip before activating the auditing" };
229  Gaudi::Property<bool> m_skipSequencers{ this, "SkipSequencers", true,
230  "If true, auditing will be skipped for Sequencer objects." };
231 
232  bool m_audit = true;
233  unsigned long long m_nEvts = 0;
234  unsigned long long m_sampleEventCount =
235  0;
236  bool m_inFullAudit = false;
238  };
239 
253  class HeapProfiler : public AuditorBase {
254 
255  public:
257  using AuditorBase::AuditorBase;
258 
259  protected:
260  void google_before( const std::string& s ) override { HeapProfilerStart( s.c_str() ); }
261 
262  void google_after( const std::string& s ) override {
263  if ( m_dumpProfileHeaps ) { HeapProfilerDump( s.c_str() ); }
264  if ( m_printProfilesToLog ) {
265  const char* profile = GetHeapProfile();
266  info() << profile << endmsg;
267  delete profile;
268  }
269  HeapProfilerStop();
270  }
271 
272  bool alreadyRunning() override { return IsHeapProfilerRunning(); }
273 
274  private:
275  Gaudi::Property<bool> m_dumpProfileHeaps{ this, "DumpHeapProfiles", true, "" };
276  Gaudi::Property<bool> m_printProfilesToLog{ this, "PrintProfilesToLog", false, "" };
277  };
278 
292  class HeapChecker : public AuditorBase {
293 
294  public:
296  using AuditorBase::AuditorBase;
297 
298  StatusCode initialize() override {
299  const StatusCode sc = AuditorBase::initialize();
300  if ( sc.isFailure() ) return sc;
301 
302  const char* HEAPCHECK = getenv( "HEAPCHECK" );
303  if ( !HEAPCHECK ) {
304  fatal() << "Environment variable HEAPCHECK must be set to 'local'" << endmsg;
305  return StatusCode::FAILURE;
306  }
307  if ( std::string( HEAPCHECK ) != "local" ) {
308  warning() << "Environment variable HEAPCHECK is set to " << HEAPCHECK
309  << " Partial Program Heap Checking is disabled" << endmsg;
310  m_enabled = false;
311  }
312 
313  return sc;
314  }
315 
316  protected:
317  void google_before( const std::string& s ) override {
318  if ( m_enabled && !m_checker ) { m_checker.reset( new HeapLeakChecker( s.c_str() ) ); }
319  }
320 
321  void google_after( const std::string& s ) override {
322  if ( m_enabled && m_checker ) {
323  if ( !m_checker->NoLeaks() ) { warning() << "Leak detected for " << s << endmsg; }
324  m_checker.reset();
325  }
326  }
327 
328  bool alreadyRunning() override { return m_enabled && m_checker; }
329 
330  private:
331  bool m_enabled = true;
333  };
334 
348  class CPUProfiler : public AuditorBase {
349 
350  public:
351  using AuditorBase::AuditorBase;
352 
353  protected:
354  void google_before( const std::string& s ) override {
355  if ( !m_running ) {
356  m_running = true;
357  ProfilerStart( ( s + ".prof" ).c_str() );
358  }
359  }
360 
361  void google_after( const std::string& ) override {
362  if ( m_running ) {
363  ProfilerStop();
364  m_running = false;
365  }
366  }
367 
368  bool alreadyRunning() override { return m_running; }
369 
370  private:
371  bool m_running = false;
372  };
373 
377 } // namespace Google
Google::AuditorBase::after
void after(CustomEventTypeRef type, const std::string &s, const StatusCode &) override
Definition: GoogleAuditor.cpp:181
MSG::DEBUG
@ DEBUG
Definition: IMessageSvc.h:25
Google::AuditorBase::before
void before(CustomEventTypeRef type, const std::string &s) override
Definition: GoogleAuditor.cpp:151
Google::HeapProfiler::google_before
void google_before(const std::string &s) override
Start the google tool.
Definition: GoogleAuditor.cpp:260
Google::AuditorBase::m_freq
Gaudi::Property< int > m_freq
Definition: GoogleAuditor.cpp:221
std::string
STL class.
IAuditor::Execute
@ Execute
Definition: IAuditor.h:34
Google::HeapProfiler::m_dumpProfileHeaps
Gaudi::Property< bool > m_dumpProfileHeaps
Definition: GoogleAuditor.cpp:275
GaudiException.h
gaudirun.s
string s
Definition: gaudirun.py:346
std::find
T find(T... args)
Google::AuditorBase::after
void after(StandardEventType type, INamedInterface *i, const StatusCode &sc) override
Definition: GoogleAuditor.cpp:163
Google::AuditorBase::m_inFullAudit
bool m_inFullAudit
Internal flag to indicate if we are current in a full event audit.
Definition: GoogleAuditor.cpp:236
Google::HeapChecker::alreadyRunning
bool alreadyRunning() override
check if we are already running the tool
Definition: GoogleAuditor.cpp:328
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:141
Google::AuditorBase::isPhaseEnabled
bool isPhaseEnabled(CustomEventTypeRef type) const
Check if auditing is enabled for the current processing phase.
Definition: GoogleAuditor.cpp:94
Google::AuditorBase::initialize
StatusCode initialize() override
Initialize the auditor base.
Definition: GoogleAuditor.cpp:44
Google::AuditorBase::m_skipSequencers
Gaudi::Property< bool > m_skipSequencers
Definition: GoogleAuditor.cpp:229
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:190
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:188
IIncidentSvc.h
Google::HeapChecker::google_before
void google_before(const std::string &s) override
Start the google tool.
Definition: GoogleAuditor.cpp:317
ManySmallAlgs.alg
alg
Definition: ManySmallAlgs.py:81
Google::AuditorBase::isSequencer
bool isSequencer(INamedInterface *i) const
Definition: GoogleAuditor.cpp:88
Google::AuditorBase::afterFinalize
void afterFinalize(INamedInterface *i) override
Definition: GoogleAuditor.cpp:200
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:31
Google::CPUProfiler::m_running
bool m_running
Definition: GoogleAuditor.cpp:371
Google::AuditorBase::after
void after(CustomEventTypeRef type, INamedInterface *i, const StatusCode &sc) override
Definition: GoogleAuditor.cpp:171
Google::AuditorBase::afterReinitialize
void afterReinitialize(INamedInterface *i) override
Definition: GoogleAuditor.cpp:196
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:118
IAlgorithm
Definition: IAlgorithm.h:38
Google::AuditorBase::getDumpName
std::string getDumpName(CustomEventTypeRef type, std::string_view name) const
Definition: GoogleAuditor.cpp:105
Google::HeapProfiler
Definition: GoogleAuditor.cpp:253
Google::CPUProfiler
Definition: GoogleAuditor.cpp:348
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:217
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:219
Google::AuditorBase::isComponentEnabled
bool isComponentEnabled(std::string_view name) const
Check if auditing is enabled for the given component.
Definition: GoogleAuditor.cpp:99
Google::AuditorBase::m_eventsToSkip
Gaudi::Property< unsigned long long > m_eventsToSkip
Definition: GoogleAuditor.cpp:227
Google::AuditorBase::afterInitialize
void afterInitialize(INamedInterface *i) override
Definition: GoogleAuditor.cpp:193
Google::AuditorBase::stopAudit
void stopAudit()
stop a full event audit
Definition: GoogleAuditor.cpp:78
Google::CPUProfiler::google_after
void google_after(const std::string &) override
stop the google tool
Definition: GoogleAuditor.cpp:361
Google::AuditorBase::before
void before(StandardEventType type, const std::string &s) override
Definition: GoogleAuditor.cpp:145
Google::AuditorBase::after
void after(StandardEventType type, const std::string &s, const StatusCode &sc) override
Definition: GoogleAuditor.cpp:175
Google::HeapChecker::m_checker
std::unique_ptr< HeapLeakChecker > m_checker
Definition: GoogleAuditor.cpp:332
Google::HeapChecker
Definition: GoogleAuditor.cpp:292
Google::AuditorBase::m_audit
bool m_audit
Internal flag to say if auditing is enabled or not for the current event.
Definition: GoogleAuditor.cpp:232
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:202
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:331
Google::AuditorBase::m_when
Gaudi::Property< std::vector< std::string > > m_when
Definition: GoogleAuditor.cpp:213
Google::AuditorBase::m_nEvts
unsigned long long m_nEvts
Number of events processed.
Definition: GoogleAuditor.cpp:233
Google::HeapChecker::google_after
void google_after(const std::string &s) override
stop the google tool
Definition: GoogleAuditor.cpp:321
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:199
Google::AuditorBase::google_after
virtual void google_after(const std::string &s)=0
stop the google tool
gaudirun.type
type
Definition: gaudirun.py:160
INamedInterface
Definition: INamedInterface.h:25
StatusCode::SUCCESS
constexpr static const auto SUCCESS
Definition: StatusCode.h:100
Google::AuditorBase::startAudit
void startAudit()
Start a full event audit.
Definition: GoogleAuditor.cpp:68
Google::AuditorBase::m_nSampleEvents
Gaudi::Property< unsigned long long > m_nSampleEvents
Definition: GoogleAuditor.cpp:225
Google::CPUProfiler::alreadyRunning
bool alreadyRunning() override
check if we are already running the tool
Definition: GoogleAuditor.cpp:368
Google::HeapChecker::initialize
StatusCode initialize() override
Initialize the auditor base.
Definition: GoogleAuditor.cpp:298
IIncidentListener.h
DECLARE_COMPONENT
#define DECLARE_COMPONENT(type)
Definition: PluginServiceV1.h:46
Google::HeapProfiler::m_printProfilesToLog
Gaudi::Property< bool > m_printProfilesToLog
Definition: GoogleAuditor.cpp:276
Google::AuditorBase::finalize
StatusCode finalize() override
Finalize the auditor base.
Definition: GoogleAuditor.cpp:61
Google::AuditorBase::m_fullEventAudit
Gaudi::Property< bool > m_fullEventAudit
Definition: GoogleAuditor.cpp:222
Google::AuditorBase::m_sampleEventCount
unsigned long long m_sampleEventCount
Internal count of the number of events currently processed during an audit.
Definition: GoogleAuditor.cpp:234
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:237
IAlgorithm.h
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:101
Google::AuditorBase
Definition: GoogleAuditor.cpp:37
IIncidentSvc
Definition: IIncidentSvc.h:33
Google::AuditorBase::beforeReinitialize
void beforeReinitialize(INamedInterface *i) override
Definition: GoogleAuditor.cpp:189
Google::AuditorBase::beforeFinalize
void beforeFinalize(INamedInterface *i) override
Definition: GoogleAuditor.cpp:191
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:28
Gaudi::Property
Implementation of property with value of concrete type.
Definition: Property.h:37
Google::HeapProfiler::google_after
void google_after(const std::string &s) override
stop the google tool
Definition: GoogleAuditor.cpp:262
Google::CPUProfiler::google_before
void google_before(const std::string &s) override
Start the google tool.
Definition: GoogleAuditor.cpp:354
MsgStream.h
Google::AuditorBase::before
void before(StandardEventType type, INamedInterface *i) override
Definition: GoogleAuditor.cpp:137
Auditor.h
Google::HeapProfiler::alreadyRunning
bool alreadyRunning() override
check if we are already running the tool
Definition: GoogleAuditor.cpp:272