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 declareProperty("ActivateAt", m_when = boost::assign::list_of
00295 ("Initialize")
00296 ("ReInitialize")
00297 ("Execute")
00298 ("BeginRun")
00299 ("EndRun")
00300 ("Finalize"),
00301 "List of phases to activate the Auditoring during" );
00302 declareProperty("DisableFor", m_veto,
00303 "List of component names to disable the auditing for" );
00304 declareProperty("EnableFor", m_list );
00305 declareProperty("ProfileFreq", m_freq = -1,
00306 "The frequence to audit events. -1 means all events" );
00307 declareProperty("DoFullEventProfile", m_fullEventAudit = false,
00308 "If true, instead of individually auditing components, the full event (or events) will be audited in one go" );
00309 declareProperty("FullEventNSampleEvents", m_nSampleEvents = 1,
00310 "The number of events to include in a full event audit, if enabled" );
00311 declareProperty("SkipEvents", m_eventsToSkip = 0,
00312 "Number of events to skip before activating the auditing" );
00313 declareProperty("SkipSequencers", m_skipSequencers = true,
00314 "If true, auditing will be skipped for Sequencer objects." );
00315 }
00316
00330 class HeapProfiler : public AuditorBase
00331 {
00332
00333 public:
00334
00336 HeapProfiler( const std::string& name, ISvcLocator* pSvcLocator)
00337 : AuditorBase( name, pSvcLocator )
00338 {
00339 declareProperty( "DumpHeapProfiles", m_dumpProfileHeaps = true );
00340 declareProperty( "PrintProfilesToLog", m_printProfilesToLog = false );
00341 }
00342
00343 protected:
00344
00345 void google_before(const std::string& s)
00346 {
00347 HeapProfilerStart(s.c_str());
00348 }
00349
00350 void google_after(const std::string& s)
00351 {
00352 if ( m_dumpProfileHeaps )
00353 {
00354 HeapProfilerDump(s.c_str());
00355 }
00356 if ( m_printProfilesToLog )
00357 {
00358 const char * profile = GetHeapProfile();
00359 m_log << MSG::INFO << profile << endmsg;
00360 delete profile;
00361 }
00362 HeapProfilerStop();
00363 }
00364
00365 bool alreadyRunning() { return IsHeapProfilerRunning(); }
00366
00367 private:
00368
00369 bool m_dumpProfileHeaps;
00370 bool m_printProfilesToLog;
00371
00372 };
00373
00387 class HeapChecker : public AuditorBase
00388 {
00389
00390 public:
00391
00393 HeapChecker( const std::string& name, ISvcLocator* pSvcLocator)
00394 : AuditorBase ( name, pSvcLocator ),
00395 m_enabled ( true ),
00396 m_checker ( NULL )
00397 { }
00398
00399 virtual ~HeapChecker() { delete m_checker; }
00400
00401 public:
00402
00403 StatusCode initialize()
00404 {
00405 const StatusCode sc = AuditorBase::initialize();
00406 if ( sc.isFailure() ) return sc;
00407
00408 const char * HEAPCHECK = getenv("HEAPCHECK");
00409 if ( !HEAPCHECK )
00410 {
00411 m_log << MSG::FATAL
00412 << "Environment variable HEAPCHECK must be set to 'local'"
00413 << endmsg;
00414 return StatusCode::FAILURE;
00415 }
00416 if ( std::string(HEAPCHECK) != "local" )
00417 {
00418 m_log << MSG::WARNING
00419 << "Environment variable HEAPCHECK is set to " << HEAPCHECK
00420 << " Partial Program Heap Checking is disabled"
00421 << endmsg;
00422 m_enabled = false;
00423 }
00424
00425 return sc;
00426 }
00427
00428 protected:
00429
00430 void google_before(const std::string& s)
00431 {
00432 if ( m_enabled && !m_checker )
00433 {
00434 m_checker = new HeapLeakChecker(s.c_str());
00435 }
00436 }
00437
00438 void google_after(const std::string& s)
00439 {
00440 if ( m_enabled && m_checker )
00441 {
00442 if ( ! m_checker->NoLeaks() )
00443 {
00444 m_log << MSG::WARNING << "Leak detected for " << s << endmsg;
00445 }
00446 delete m_checker;
00447 m_checker = NULL;
00448 }
00449 }
00450
00451 bool alreadyRunning() { return m_enabled && m_checker != NULL ; }
00452
00453 private:
00454
00455 bool m_enabled;
00456 HeapLeakChecker * m_checker;
00457
00458 };
00459
00473 class CPUProfiler : public AuditorBase
00474 {
00475
00476 public:
00477
00478 CPUProfiler( const std::string& name, ISvcLocator* pSvcLocator )
00479 : AuditorBase ( name, pSvcLocator ),
00480 m_running ( false )
00481 { }
00482
00483 protected:
00484
00485 void google_before(const std::string& s)
00486 {
00487 if ( !m_running )
00488 {
00489 m_running = true;
00490 ProfilerStart((s+".prof").c_str());
00491 }
00492 }
00493
00494 void google_after(const std::string&)
00495 {
00496 if ( m_running )
00497 {
00498 ProfilerStop();
00499 m_running = false;
00500 }
00501 }
00502
00503 bool alreadyRunning() { return m_running; }
00504
00505 private:
00506
00507 bool m_running;
00508
00509 };
00510
00511 DECLARE_AUDITOR_FACTORY( HeapProfiler );
00512 DECLARE_AUDITOR_FACTORY( HeapChecker );
00513 DECLARE_AUDITOR_FACTORY( CPUProfiler );
00514
00515 }