TimingAuditor.cpp
Go to the documentation of this file.
1 #include "GaudiKernel/Auditor.h"
2 #include "GaudiKernel/IToolSvc.h"
5 #include "GaudiKernel/IToolSvc.h"
7 #include "GaudiKernel/HashMap.h"
9 // ============================================================================
10 // GaudiAlg
11 // ============================================================================
13 // ============================================================================
14 #ifdef __ICC
15 // disable icc warning #654: overloaded virtual function "B::Y" is only partially overridden in class "C"
16 // TODO: there is only a partial overload of IAuditor::before and IAuditor::after
17 #pragma warning(disable:654)
18 #endif
19 
28 class TimingAuditor: public extends<Auditor,
29  IIncidentListener> {
30 public:
31 
32  void before(StandardEventType evt, INamedInterface* alg) override;
33  void after(StandardEventType evt, INamedInterface* alg, const StatusCode &sc) override;
34 
35  using Auditor::before; // avoid hiding base-class methods
36  void before(CustomEventTypeRef evt, const std::string& name) override;
37  using Auditor::after; // avoid hiding base-class methods
38  void after(CustomEventTypeRef evt, const std::string& name, const StatusCode &sc) override;
39 
40 private:
43  void i_beforeFinalize( INamedInterface* alg );
44  void i_beforeExecute( INamedInterface* alg );
45  void i_afterExecute( INamedInterface* alg);
46 
47 public:
49  void handle ( const Incident& ) override;
50 
51 public:
52  StatusCode initialize () override;
53  StatusCode finalize () override;
54 
55 public:
57  TimingAuditor ( const std::string& name, ISvcLocator* pSvc )
58  : base_class ( name , pSvc )
59  {
60  declareProperty ( "OptimizedForDOD" , m_goodForDOD ) ;
61  }
63  ~TimingAuditor() override = default;
64 
65  // delete default/copy constructor and assignment
66  TimingAuditor () = delete;
67  TimingAuditor ( const TimingAuditor& ) = delete ;
68  TimingAuditor& operator=( const TimingAuditor& ) = delete ;
69 private:
70  // tool service
72  // incident service
74  // the timer tool
76  // ApplicationManager
78  //
80  // indentation level
81  int m_indent = 0 ;
82  // "in event"
83  bool m_inEvent = false ;
84  // "optimized for Data-On-Demand Service"
85  bool m_goodForDOD = false ;
86  //
88 
89  // Whether the timing has been saved already
90  bool m_histoSaved = false ;
91 
92 
93 } ;
94 // ============================================================================
96 // ============================================================================
98 // ============================================================================
100 {
102  if ( sc.isFailure() ) { return sc ; } // RETURN
103 
104 
105  // get tool service
106  if ( ! m_toolSvc )
107  {
108  m_toolSvc = Auditor::service ( "ToolSvc" );
109  if ( !m_toolSvc )
110  {
111  error() << "Could not retrieve 'ToolSvc' " << endmsg ;
112  return StatusCode::FAILURE ; // RETURN
113  }
114  if ( !m_timer )
115  {
116  sc = m_toolSvc->retrieveTool
117  ( "SequencerTimerTool/TIMER" , m_timer , this , true ) ;
118  if ( sc.isFailure() )
119  {
120  error() << "Could not retrieve ISequencerTimerTool" << endmsg ;
121  return sc ;
122  }
123  }
124  }
125  // get incident service
126  if ( !m_incSvc )
127  {
128  m_incSvc = Auditor::service ( "IncidentSvc" );
129  if ( !m_incSvc )
130  {
131  error() << "Could not retrieve 'IncidentSvc'" << endmsg ;
132  return StatusCode::FAILURE ;
133  }
134  m_incSvc -> addListener ( this , IncidentType::BeginEvent ) ;
135  m_incSvc -> addListener ( this , IncidentType::EndEvent ) ;
136  }
137  // get the application manager
138  if ( !m_appMgr )
139  {
140  m_appMgr = Auditor::service ( "ApplicationMgr" );
141  if ( !m_appMgr )
142  {
143  error() << "Could not retrieve 'ApplicationMgr'" << endmsg ;
144  return sc ;
145  }
146  if ( m_map.end() == m_map.find( m_appMgr.get() ) )
147  {
148  m_map.insert ( m_appMgr.get() , m_timer->addTimer( "EVENT LOOP" ) ) ;
149  }
150  }
151  //
152  return StatusCode::SUCCESS ;
153 }
154 // ============================================================================
156 {
157  if ( m_incSvc )
158  {
159  m_incSvc -> removeListener ( this , IncidentType::BeginEvent ) ;
160  m_incSvc -> removeListener ( this , IncidentType::EndEvent ) ;
161  m_incSvc.reset();
162  }
163  if ( m_toolSvc )
164  {
165  // the 2 following line are commented out: it is
166  // is a temporary hack which prevent a crash due to a problem in
167  // the reference counting
168  // if ( 0 != m_timer )
169  // { m_toolSvc -> releaseTool ( m_timer ) . ignore() ; m_timer = 0 ; }
170  m_toolSvc.reset();
171  }
172  m_appMgr.reset();
173  // clear the map
174  m_map.clear() ;
175  // finalize the base class
176  return Auditor::finalize () ;
177 }
178 // ============================================================================
179 void TimingAuditor::before(StandardEventType evt, INamedInterface *alg)
180 {
181  switch (evt) {
182  case IAuditor::Initialize : i_beforeInitialize( alg ); break;
183  case IAuditor::Execute : i_beforeExecute( alg ); break;
184  case IAuditor::Finalize : i_beforeFinalize( alg ); break;
185  default: break;
186  }
187 }
188 // ============================================================================
189 void TimingAuditor::after(StandardEventType evt, INamedInterface *alg, const StatusCode &)
190 {
191  switch (evt) {
192  case IAuditor::Initialize : i_afterInitialize( alg ); break;
193  case IAuditor::Execute : i_afterExecute( alg ); break;
194  default: break;
195  }
196 }
197 // ============================================================================
199 {
200  if (!m_histoSaved)
201  {
203  m_histoSaved = true;
204  }
205 }
206 
207 // ============================================================================
209 {
210  if ( m_goodForDOD ) { return ; }
211  //
212  if ( !alg ) { return ; }
213  auto found = m_map.find( alg ) ;
214  if ( m_map.end() != found ) { return ; }
215  ++m_indent ;
216  std::string nick = alg->name() ;
217  if ( 0 < m_indent ) { nick = std::string ( m_indent , ' ') + nick ; }
218  if ( m_inEvent )
219  {
220  nick[0] = '*' ;
221  debug() << "Insert non-structural component '"
222  << alg->name() << "' of type '"
223  << System::typeinfoName(typeid(*alg)) << "' at level "
224  << m_indent << endmsg ;
225  }
226  int timer = m_timer->addTimer( nick ) ;
227  m_map.insert ( alg , timer ) ;
228  m_timer->start( timer ) ;
229 }
230 // ============================================================================
232 {
233  if ( m_goodForDOD || !alg ) { return ; }
234  --m_indent ;
235 }
236 // ============================================================================
238 {
239  if ( !alg ) { return ; }
240  ++m_indent ;
241  auto found = m_map.find( alg ) ;
242  if ( m_map.end() == found )
243  {
244  debug() << "Insert non-structural component '"
245  << alg->name() << "' of type '"
246  << System::typeinfoName(typeid(*alg)) << "' at level "
247  << m_indent << endmsg ;
248  std::string nick = alg->name() ;
249  if ( 0 < m_indent ) { nick = std::string ( m_indent , ' ') + nick ; }
250  if ( !m_goodForDOD ) { nick[0]='*' ;}
251  int timer = m_timer->addTimer( nick ) ;
252  m_map.insert ( alg , timer ) ;
253  m_timer->start( timer ) ;
254  return ;
255  }
256  m_timer->start( found->second ) ;
257 }
258 // ============================================================================
260 {
261  if ( !alg ) { return ; }
262  auto found = m_map.find( alg ) ;
263  if ( m_map.end() == found ) { return ; }
264  m_timer->stop( found->second ) ;
265  --m_indent ;
266 }
267 // ============================================================================
268 void TimingAuditor::before(CustomEventTypeRef evt, const std::string& name)
269 {
270  // Ignore obvious mistakes
271  if ( name.empty() && evt.empty() ) { return; }
272 
273  // look for the user timer in the map
274  int timer = 0;
275  std::string nick = name + ":" + evt;
276  auto found = m_mapUser.find( nick );
277 
278  if ( m_mapUser.end() == found ) {
279  // add a new timer if not yet available
280  timer = m_timer->addTimer( nick ) ;
281  m_mapUser[nick] = timer;
282  } else {
283  timer = found->second;
284  }
285  m_timer->start( timer );
286 }
287 // ============================================================================
288 void TimingAuditor::after(CustomEventTypeRef evt, const std::string& name, const StatusCode &)
289 {
290  // Ignore obvious mistakes
291  if ( name.empty() && evt.empty() ) { return; }
292 
293  // look for the user timer in the map
294  std::string nick = name + ":" + evt;
295  auto found = m_mapUser.find( nick );
296 
297  // We cannot do much if the timer is not available
298  if ( m_mapUser.end() == found ) {
299  warning() << "Trying to stop the measure of the timing for '"
300  << nick << "' but it was never started. Check the code"
301  << endmsg;
302  return;
303  }
304  m_timer->stop( found->second );
305 }
306 // ============================================================================
308 {
309  if ( IncidentType::BeginEvent == i.type () ) {
310  m_timer -> start ( m_map[ m_appMgr.get() ] ) ;
311  ++m_indent ;
312  m_inEvent = true ;
313  } else if ( IncidentType::EndEvent == i.type () ) {
314  m_timer -> stop ( m_map[ m_appMgr.get() ] ) ;
315  --m_indent ;
316  m_inEvent = false ;
317  }
318 }
319 // ============================================================================
320 // The END
321 // ============================================================================
void i_afterInitialize(INamedInterface *alg)
void i_beforeInitialize(INamedInterface *alg)
TimingAuditor & operator=(const TimingAuditor &)=delete
virtual StatusCode finalize()
Definition: Auditor.cpp:198
T empty(T...args)
StatusCode service(const std::string &name, T *&svc, bool createIf=false) const
Access a service by name, creating it if it doesn't already exist.
Definition: Auditor.h:110
def initialize()
Definition: AnalysisTest.py:12
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
const std::string & type() const
Access to the incident type.
Definition: Incident.h:41
TimingAuditor(const std::string &name, ISvcLocator *pSvc)
standard constructor
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:297
virtual int addTimer(const std::string &name)=0
add a timer entry with the specified name
bool m_inEvent
"In event" flag
StatusCode finalize() override
void i_beforeExecute(INamedInterface *alg)
result_type insert(const key_type &key, const mapped_type &mapped)
insert the (key,value) pair into the container
Definition: VectorMap.h:317
void after(StandardEventType evt, INamedInterface *alg, const StatusCode &sc) override
bool isFailure() const
Test for a status code of FAILURE.
Definition: StatusCode.h:86
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:36
virtual const std::string & name() const =0
Retrieve the name of the instance.
STL class.
GaudiUtils::HashMap< std::string, int > m_mapUser
map used to record user timing events
StatusCode initialize() override
factory:
iterator find(const key_type &key) const
find the element by key
Definition: VectorMap.h:455
TYPE * get() const
Get interface pointer.
Definition: SmartIF.h:76
int m_indent
indentation level
Property * declareProperty(const std::string &name, T &property, const std::string &doc="none") const
Declare the named property.
Definition: Auditor.h:232
iterator end() const
"end" iterator for sequential access (const-only version!)
Definition: VectorMap.h:198
iterator end()
Definition: Map.h:132
SmartIF< INamedInterface > m_appMgr
ApplicationManager.
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
SmartIF< IIncidentSvc > m_incSvc
incident service
void before(StandardEventType evt, INamedInterface *alg) override
virtual void saveHistograms()=0
prepares and saves the timing histograms
iterator find(const key_type &key)
Definition: Map.h:149
void after(StandardEventType, INamedInterface *, const StatusCode &) override
Definition: Auditor.cpp:107
~TimingAuditor() override=default
destructor
GaudiUtils::VectorMap< const INamedInterface *, int > m_map
void i_beforeFinalize(INamedInterface *alg)
virtual void start(int index)=0
start the counter, i.e.
IInterface compliant class extending IInterface with the name() method.
TimingAuditor()=delete
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
Base class used to extend a class implementing other interfaces.
Definition: extends.h:10
Base class for all Incidents (computing events).
Definition: Incident.h:17
Implements the time measurement inside a sequencer.
const std::string & name() const override
Definition: Auditor.cpp:202
void clear()
clear the container
Definition: VectorMap.h:497
SmartIF< IToolSvc > m_toolSvc
tool service
void reset(TYPE *ptr=nullptr)
Set the internal pointer to the passed one disposing of the old one.
Definition: SmartIF.h:88
ISequencerTimerTool * m_timer
the timer tool
virtual StatusCode initialize()
Definition: Auditor.cpp:82
bool m_goodForDOD
"optimized for DOD"
void handle(const Incident &) override
Inform that a new incident has occurred.
list i
Definition: ana.py:128
virtual double stop(int index)=0
stop the counter, return the elapsed time
void before(StandardEventType, INamedInterface *) override
The following methods are meant to be implemented by the child class...
Definition: Auditor.cpp:87
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
tuple start
Definition: IOTest.py:88
void i_afterExecute(INamedInterface *alg)
Simple auditor which uses SequencerTimerTool for ALL algorithms, including the algorithm from main Ga...