00001
00002 #include <vector>
00003 #include <string>
00004 #include <utility>
00005 #include <memory>
00006 #include <algorithm>
00007
00008 #include "GaudiKernel/AudFactory.h"
00009 #include "GaudiKernel/Auditor.h"
00010 #include "GaudiKernel/IAuditorSvc.h"
00011 #include "GaudiKernel/GaudiException.h"
00012 #include "GaudiKernel/MsgStream.h"
00013 #include "GaudiKernel/IIncidentListener.h"
00014 #include "GaudiKernel/IIncidentSvc.h"
00015
00016 #include "GaudiAlg/GaudiSequencer.h"
00017 #include "GaudiAlg/Sequencer.h"
00018
00019 #include "boost/assign/list_of.hpp"
00020
00021 #include "google/heap-profiler.h"
00022 #include "google/heap-checker.h"
00023 #include "google/profiler.h"
00024
00025 namespace Google
00026 {
00027
00035 class AuditorBase : public extends1<Auditor, IIncidentListener>
00036 {
00037
00038 public:
00039
00041 AuditorBase( const std::string& name, ISvcLocator* pSvcLocator);
00042
00044 virtual ~AuditorBase() { }
00045
00047 StatusCode initialize()
00048 {
00049 m_log << MSG::INFO << "Initialised" << endmsg;
00050
00051 SmartIF<IIncidentSvc> inSvc(serviceLocator()->service("IncidentSvc"));
00052 if ( ! inSvc.isValid() ) return StatusCode::FAILURE;
00053
00054 inSvc->addListener( this, IncidentType::BeginEvent );
00055
00056 return StatusCode::SUCCESS;
00057 }
00058
00060 StatusCode finalize()
00061 {
00062 if ( alreadyRunning() ) stopAudit();
00063 return StatusCode::SUCCESS;
00064 }
00065
00066 private:
00067
00069 void startAudit()
00070 {
00071 m_log << MSG::INFO << " -> Starting full audit from event " << m_nEvts << " to "
00072 << m_nEvts+m_nSampleEvents << endmsg;
00073 m_inFullAudit = true;
00074 m_sampleEventCount = 1;
00075 std::ostringstream t;
00076 t << "FULL-Events" << m_nEvts << "To" << m_nEvts+m_nSampleEvents ;
00077 google_before(t.str());
00078 }
00079
00081 void stopAudit()
00082 {
00083 m_log << MSG::INFO << " -> Stopping full audit" << endmsg;
00084 std::ostringstream t;
00085 t << "FULL-Events" << m_nEvts << "To" << m_nEvts+m_nSampleEvents ;
00086 google_after(t.str());
00087 m_inFullAudit = false;
00088 m_sampleEventCount = 0;
00089 }
00090
00093 bool isSequencer( INamedInterface* i ) const
00094 {
00095 return ( dynamic_cast<GaudiSequencer*>(i) != NULL ||
00096 dynamic_cast<Sequencer*>(i) != NULL );
00097 }
00098
00099 public:
00100
00106 void handle( const Incident& incident )
00107 {
00108 if ( IncidentType::BeginEvent == incident.type() )
00109 {
00110 ++m_nEvts;
00111 m_audit = ( m_nEvts > m_eventsToSkip &&
00112 ( m_freq < 0 ||
00113 m_nEvts == 1 ||
00114 m_nEvts % m_freq == 0 ) );
00115 m_log << MSG::DEBUG << "Event " << m_nEvts
00116 << " Audit=" << m_audit << endmsg;
00117 if ( m_fullEventAudit )
00118 {
00119 if ( m_inFullAudit )
00120 {
00121 if ( m_sampleEventCount >= m_nSampleEvents &&
00122 alreadyRunning() )
00123 {
00124 stopAudit();
00125 }
00126 else
00127 {
00128 ++m_sampleEventCount;
00129 }
00130 }
00131 if ( m_audit && !m_inFullAudit && !alreadyRunning() )
00132 {
00133 startAudit();
00134 }
00135 }
00136 }
00137 }
00138
00139 public:
00140
00141 void before(StandardEventType type, INamedInterface* i)
00142 {
00143 if ( !m_skipSequencers || !isSequencer(i) )
00144 {
00145 before(type,i->name());
00146 }
00147 }
00148
00149 void before(CustomEventTypeRef type, INamedInterface* i)
00150 {
00151 if ( !m_skipSequencers || !isSequencer(i) )
00152 {
00153 before(type,i->name());
00154 }
00155 }
00156
00157 void before(StandardEventType type, const std::string& s)
00158 {
00159 std::ostringstream t;
00160 t << type;
00161 before(t.str(),s);
00162 }
00163
00164 void before(CustomEventTypeRef, const std::string& s)
00165 {
00166 if ( !m_fullEventAudit && m_audit &&
00167 std::find(m_veto.begin(),m_veto.end(),s) == m_veto.end() &&
00168 ( m_list.empty() || std::find(m_list.begin(),m_list.end(),s) != m_list.end() ) )
00169 {
00170 if ( !alreadyRunning() )
00171 {
00172 m_log << MSG::INFO << "Starting Auditor for " << s << endmsg;
00173 m_startedBy = s;
00174 std::ostringstream t;
00175 t << s << "-Event" << m_nEvts;
00176 google_before(t.str());
00177 }
00178 else
00179 {
00180 m_log << MSG::WARNING
00181 << "Auditor already running. Cannot be started for " << s
00182 << endmsg;
00183 }
00184 }
00185 }
00186
00187 void after(StandardEventType type, INamedInterface* i, const StatusCode& sc)
00188 {
00189 if ( !m_skipSequencers || !isSequencer(i) )
00190 {
00191 std::ostringstream t;
00192 t << type;
00193 after(t.str(),i,sc);
00194 }
00195 }
00196
00197 void after(CustomEventTypeRef type, INamedInterface* i, const StatusCode& sc)
00198 {
00199 if ( !m_skipSequencers || !isSequencer(i) )
00200 {
00201 after(type,i->name(),sc);
00202 }
00203 }
00204
00205 void after(StandardEventType type, const std::string& s, const StatusCode& sc)
00206 {
00207 std::ostringstream t;
00208 t << type;
00209 after(t.str(),s,sc);
00210 }
00211
00212 void after(CustomEventTypeRef, const std::string& s, const StatusCode&)
00213 {
00214 if ( !m_fullEventAudit && m_audit &&
00215 std::find(m_veto.begin(),m_veto.end(),s) == m_veto.end() &&
00216 ( m_list.empty() || std::find(m_list.begin(),m_list.end(),s) != m_list.end() ) )
00217 {
00218 if ( s == m_startedBy )
00219 {
00220 std::ostringstream t;
00221 t << s << "-Event" << m_nEvts;
00222 google_after(t.str());
00223 }
00224 }
00225 }
00226
00227
00228 void beforeInitialize (INamedInterface *i) { return before(IAuditor::Initialize,i); }
00229 void beforeReinitialize(INamedInterface *i) { return before(IAuditor::ReInitialize,i); }
00230 void beforeExecute (INamedInterface *i) { return before(IAuditor::Execute,i); }
00231 void beforeBeginRun (INamedInterface *i) { return before(IAuditor::BeginRun,i); }
00232 void beforeEndRun (INamedInterface *i) { return before(IAuditor::EndRun,i); }
00233 void beforeFinalize (INamedInterface *i) { return before(IAuditor::Finalize,i); }
00234
00235 void afterInitialize (INamedInterface *i) { return after(IAuditor::Initialize,i,StatusCode::SUCCESS); }
00236 void afterReinitialize (INamedInterface *i) { return after(IAuditor::ReInitialize,i,StatusCode::SUCCESS); }
00237 void afterExecute (INamedInterface *i, const StatusCode& s) { return after(IAuditor::Execute,i,s); }
00238 void afterBeginRun (INamedInterface *i) { return after(IAuditor::BeginRun,i,StatusCode::SUCCESS); }
00239 void afterEndRun (INamedInterface *i) { return after(IAuditor::EndRun,i,StatusCode::SUCCESS); }
00240 void afterFinalize (INamedInterface *i) { return after(IAuditor::Finalize,i,StatusCode::SUCCESS); }
00241
00242 protected:
00243
00245 virtual void google_before(const std::string& s) = 0;
00246
00248 virtual void google_after(const std::string& s) = 0;
00249
00251 virtual bool alreadyRunning() = 0;
00252
00253 protected:
00254
00255 mutable MsgStream m_log;
00256
00257 private:
00258
00259 std::vector<std::string> m_when;
00260 std::vector<std::string> m_veto;
00261 std::vector<std::string> m_list;
00262
00263 unsigned long long m_eventsToSkip;
00264
00265 bool m_skipSequencers;
00266
00267 int m_freq;
00268
00269 bool m_audit;
00270
00271 unsigned long long m_nEvts;
00272
00273 bool m_fullEventAudit;
00274
00275 unsigned long long m_nSampleEvents;
00276
00277 unsigned long long m_sampleEventCount;
00278
00279 bool m_inFullAudit;
00280
00281 std::string m_startedBy;
00282
00283 };
00284
00285 AuditorBase::AuditorBase( const std::string& name,
00286 ISvcLocator* pSvcLocator )
00287 : base_class ( name , pSvcLocator )
00288 , m_log ( msgSvc() , name )
00289 , m_audit ( false )
00290 , m_nEvts ( 0 )
00291 , m_sampleEventCount( 0 )
00292 , m_inFullAudit ( false )
00293 {
00294 m_when =
00295 #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
00296 {
00297 "Initialize",
00298 "ReInitialize",
00299 "Execute",
00300 "BeginRun",
00301 "EndRun",
00302 "Finalize"
00303 }
00304 #else
00305 boost::assign::list_of
00306 ("Initialize")
00307 ("ReInitialize")
00308 ("Execute")
00309 ("BeginRun")
00310 ("EndRun")
00311 ("Finalize")
00312 #endif
00313 ;
00314 declareProperty("ActivateAt", m_when,
00315 "List of phases to activate the Auditoring during" );
00316 declareProperty("DisableFor", m_veto,
00317 "List of component names to disable the auditing for" );
00318 declareProperty("EnableFor", m_list );
00319 declareProperty("ProfileFreq", m_freq = -1,
00320 "The frequence to audit events. -1 means all events" );
00321 declareProperty("DoFullEventProfile", m_fullEventAudit = false,
00322 "If true, instead of individually auditing components, the full event (or events) will be audited in one go" );
00323 declareProperty("FullEventNSampleEvents", m_nSampleEvents = 1,
00324 "The number of events to include in a full event audit, if enabled" );
00325 declareProperty("SkipEvents", m_eventsToSkip = 0,
00326 "Number of events to skip before activating the auditing" );
00327 declareProperty("SkipSequencers", m_skipSequencers = true,
00328 "If true, auditing will be skipped for Sequencer objects." );
00329 }
00330
00344 class HeapProfiler : public AuditorBase
00345 {
00346
00347 public:
00348
00350 HeapProfiler( const std::string& name, ISvcLocator* pSvcLocator)
00351 : AuditorBase( name, pSvcLocator )
00352 {
00353 declareProperty( "DumpHeapProfiles", m_dumpProfileHeaps = true );
00354 declareProperty( "PrintProfilesToLog", m_printProfilesToLog = false );
00355 }
00356
00357 protected:
00358
00359 void google_before(const std::string& s)
00360 {
00361 HeapProfilerStart(s.c_str());
00362 }
00363
00364 void google_after(const std::string& s)
00365 {
00366 if ( m_dumpProfileHeaps )
00367 {
00368 HeapProfilerDump(s.c_str());
00369 }
00370 if ( m_printProfilesToLog )
00371 {
00372 const char * profile = GetHeapProfile();
00373 m_log << MSG::INFO << profile << endmsg;
00374 delete profile;
00375 }
00376 HeapProfilerStop();
00377 }
00378
00379 bool alreadyRunning() { return IsHeapProfilerRunning(); }
00380
00381 private:
00382
00383 bool m_dumpProfileHeaps;
00384 bool m_printProfilesToLog;
00385
00386 };
00387
00401 class HeapChecker : public AuditorBase
00402 {
00403
00404 public:
00405
00407 HeapChecker( const std::string& name, ISvcLocator* pSvcLocator)
00408 : AuditorBase ( name, pSvcLocator ),
00409 m_enabled ( true ),
00410 m_checker ( NULL )
00411 { }
00412
00413 virtual ~HeapChecker() { delete m_checker; }
00414
00415 public:
00416
00417 StatusCode initialize()
00418 {
00419 const StatusCode sc = AuditorBase::initialize();
00420 if ( sc.isFailure() ) return sc;
00421
00422 const char * HEAPCHECK = getenv("HEAPCHECK");
00423 if ( !HEAPCHECK )
00424 {
00425 m_log << MSG::FATAL
00426 << "Environment variable HEAPCHECK must be set to 'local'"
00427 << endmsg;
00428 return StatusCode::FAILURE;
00429 }
00430 if ( std::string(HEAPCHECK) != "local" )
00431 {
00432 m_log << MSG::WARNING
00433 << "Environment variable HEAPCHECK is set to " << HEAPCHECK
00434 << " Partial Program Heap Checking is disabled"
00435 << endmsg;
00436 m_enabled = false;
00437 }
00438
00439 return sc;
00440 }
00441
00442 protected:
00443
00444 void google_before(const std::string& s)
00445 {
00446 if ( m_enabled && !m_checker )
00447 {
00448 m_checker = new HeapLeakChecker(s.c_str());
00449 }
00450 }
00451
00452 void google_after(const std::string& s)
00453 {
00454 if ( m_enabled && m_checker )
00455 {
00456 if ( ! m_checker->NoLeaks() )
00457 {
00458 m_log << MSG::WARNING << "Leak detected for " << s << endmsg;
00459 }
00460 delete m_checker;
00461 m_checker = NULL;
00462 }
00463 }
00464
00465 bool alreadyRunning() { return m_enabled && m_checker != NULL ; }
00466
00467 private:
00468
00469 bool m_enabled;
00470 HeapLeakChecker * m_checker;
00471
00472 };
00473
00487 class CPUProfiler : public AuditorBase
00488 {
00489
00490 public:
00491
00492 CPUProfiler( const std::string& name, ISvcLocator* pSvcLocator )
00493 : AuditorBase ( name, pSvcLocator ),
00494 m_running ( false )
00495 { }
00496
00497 protected:
00498
00499 void google_before(const std::string& s)
00500 {
00501 if ( !m_running )
00502 {
00503 m_running = true;
00504 ProfilerStart((s+".prof").c_str());
00505 }
00506 }
00507
00508 void google_after(const std::string&)
00509 {
00510 if ( m_running )
00511 {
00512 ProfilerStop();
00513 m_running = false;
00514 }
00515 }
00516
00517 bool alreadyRunning() { return m_running; }
00518
00519 private:
00520
00521 bool m_running;
00522
00523 };
00524
00525 DECLARE_AUDITOR_FACTORY( HeapProfiler )
00526 DECLARE_AUDITOR_FACTORY( HeapChecker )
00527 DECLARE_AUDITOR_FACTORY( CPUProfiler )
00528
00529 }