Gaudi Framework, version v23r2

Home   Generated: Thu Jun 28 2012

GoogleAuditor.cpp

Go to the documentation of this file.
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     // Obsolete methods
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Thu Jun 28 2012 23:27:27 for Gaudi Framework, version v23r2 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004