All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
TimingAuditor.cpp
Go to the documentation of this file.
1 #include "GaudiKernel/Auditor.h"
2 #include "GaudiKernel/HashMap.h"
5 #include "GaudiKernel/IToolSvc.h"
6 #include "GaudiKernel/IToolSvc.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, IIncidentListener>
29 {
30 public:
31  void before( StandardEventType evt, INamedInterface* alg ) override;
32  void after( StandardEventType evt, INamedInterface* alg, const StatusCode& sc ) override;
33 
34  using Auditor::before; // avoid hiding base-class methods
35  void before( CustomEventTypeRef evt, const std::string& name ) override;
36  using Auditor::after; // avoid hiding base-class methods
37  void after( CustomEventTypeRef evt, const std::string& name, const StatusCode& sc ) override;
38 
39 private:
42  void i_beforeFinalize( INamedInterface* alg );
43  void i_beforeExecute( INamedInterface* alg );
44  void i_afterExecute( INamedInterface* alg );
45 
46 public:
48  void handle( const Incident& ) override;
49 
50 public:
51  StatusCode initialize() override;
52  StatusCode finalize() override;
53 
54 public:
55  using extends::extends;
57  ~TimingAuditor() override = default;
58 
59  // delete default/copy constructor and assignment
60  TimingAuditor() = delete;
61  TimingAuditor( const TimingAuditor& ) = delete;
62  TimingAuditor& operator=( const TimingAuditor& ) = delete;
63 
64 private:
65  // tool service
67  // incident service
69  // the timer tool
71  // ApplicationManager
73  //
75  // indentation level
76  int m_indent = 0;
77  // "in event"
78  bool m_inEvent = false;
79  //
81 
82  // Whether the timing has been saved already
83  bool m_histoSaved = false;
84 
85  Gaudi::Property<bool> m_goodForDOD{this, "OptimizedForDOD", false, "enable optimization for Data-On-Demand Service"};
86 };
87 // ============================================================================
89 // ============================================================================
91 // ============================================================================
93 {
95  if ( sc.isFailure() ) {
96  return sc;
97  } // RETURN
98 
99  // get tool service
100  if ( !m_toolSvc ) {
101  m_toolSvc = Auditor::service( "ToolSvc" );
102  if ( !m_toolSvc ) {
103  error() << "Could not retrieve 'ToolSvc' " << endmsg;
104  return StatusCode::FAILURE; // RETURN
105  }
106  if ( !m_timer ) {
107  sc = m_toolSvc->retrieveTool( "SequencerTimerTool/TIMER", m_timer, this, true );
108  if ( sc.isFailure() ) {
109  error() << "Could not retrieve ISequencerTimerTool" << endmsg;
110  return sc;
111  }
112  }
113  }
114  // get incident service
115  if ( !m_incSvc ) {
116  m_incSvc = Auditor::service( "IncidentSvc" );
117  if ( !m_incSvc ) {
118  error() << "Could not retrieve 'IncidentSvc'" << endmsg;
119  return StatusCode::FAILURE;
120  }
121  m_incSvc->addListener( this, IncidentType::BeginEvent );
122  m_incSvc->addListener( this, IncidentType::EndEvent );
123  }
124  // get the application manager
125  if ( !m_appMgr ) {
126  m_appMgr = Auditor::service( "ApplicationMgr" );
127  if ( !m_appMgr ) {
128  error() << "Could not retrieve 'ApplicationMgr'" << endmsg;
129  return sc;
130  }
131  if ( m_map.end() == m_map.find( m_appMgr.get() ) ) {
132  m_map.insert( m_appMgr.get(), m_timer->addTimer( "EVENT LOOP" ) );
133  }
134  }
135  //
136  return StatusCode::SUCCESS;
137 }
138 // ============================================================================
140 {
141  if ( m_incSvc ) {
142  m_incSvc->removeListener( this, IncidentType::BeginEvent );
143  m_incSvc->removeListener( this, IncidentType::EndEvent );
144  m_incSvc.reset();
145  }
146  if ( m_toolSvc ) {
147  // the 2 following line are commented out: it is
148  // is a temporary hack which prevent a crash due to a problem in
149  // the reference counting
150  // if ( 0 != m_timer )
151  // { m_toolSvc -> releaseTool ( m_timer ) . ignore() ; m_timer = 0 ; }
152  m_toolSvc.reset();
153  }
154  m_appMgr.reset();
155  // clear the map
156  m_map.clear();
157  // finalize the base class
158  return Auditor::finalize();
159 }
160 // ============================================================================
161 void TimingAuditor::before( StandardEventType evt, INamedInterface* alg )
162 {
163  switch ( evt ) {
165  i_beforeInitialize( alg );
166  break;
167  case IAuditor::Execute:
168  i_beforeExecute( alg );
169  break;
170  case IAuditor::Finalize:
171  i_beforeFinalize( alg );
172  break;
173  default:
174  break;
175  }
176 }
177 // ============================================================================
178 void TimingAuditor::after( StandardEventType evt, INamedInterface* alg, const StatusCode& )
179 {
180  switch ( evt ) {
182  i_afterInitialize( alg );
183  break;
184  case IAuditor::Execute:
185  i_afterExecute( alg );
186  break;
187  default:
188  break;
189  }
190 }
191 // ============================================================================
193 {
194  if ( !m_histoSaved ) {
196  m_histoSaved = true;
197  }
198 }
199 
200 // ============================================================================
202 {
203  if ( m_goodForDOD ) {
204  return;
205  }
206  //
207  if ( !alg ) {
208  return;
209  }
210  auto found = m_map.find( alg );
211  if ( m_map.end() != found ) {
212  return;
213  }
214  ++m_indent;
215  std::string nick = alg->name();
216  if ( 0 < m_indent ) {
217  nick = std::string( m_indent, ' ' ) + nick;
218  }
219  if ( m_inEvent ) {
220  nick[0] = '*';
221  debug() << "Insert non-structural component '" << alg->name() << "' of type '"
222  << System::typeinfoName( typeid( *alg ) ) << "' at level " << m_indent << endmsg;
223  }
224  int timer = m_timer->addTimer( nick );
225  m_map.insert( alg, timer );
226  m_timer->start( timer );
227 }
228 // ============================================================================
230 {
231  if ( m_goodForDOD || !alg ) {
232  return;
233  }
234  --m_indent;
235 }
236 // ============================================================================
238 {
239  if ( !alg ) {
240  return;
241  }
242  ++m_indent;
243  auto found = m_map.find( alg );
244  if ( m_map.end() == found ) {
245  debug() << "Insert non-structural component '" << alg->name() << "' of type '"
246  << System::typeinfoName( typeid( *alg ) ) << "' at level " << m_indent << endmsg;
247  std::string nick = alg->name();
248  if ( 0 < m_indent ) {
249  nick = std::string( m_indent, ' ' ) + nick;
250  }
251  if ( !m_goodForDOD ) {
252  nick[0] = '*';
253  }
254  int timer = m_timer->addTimer( nick );
255  m_map.insert( alg, timer );
256  m_timer->start( timer );
257  return;
258  }
259  m_timer->start( found->second );
260 }
261 // ============================================================================
263 {
264  if ( !alg ) {
265  return;
266  }
267  auto found = m_map.find( alg );
268  if ( m_map.end() == found ) {
269  return;
270  }
271  m_timer->stop( found->second );
272  --m_indent;
273 }
274 // ============================================================================
275 void TimingAuditor::before( CustomEventTypeRef evt, const std::string& name )
276 {
277  // Ignore obvious mistakes
278  if ( name.empty() && evt.empty() ) {
279  return;
280  }
281 
282  // look for the user timer in the map
283  int timer = 0;
284  std::string nick = name + ":" + evt;
285  auto found = m_mapUser.find( nick );
286 
287  if ( m_mapUser.end() == found ) {
288  // add a new timer if not yet available
289  timer = m_timer->addTimer( nick );
290  m_mapUser[nick] = timer;
291  } else {
292  timer = found->second;
293  }
294  m_timer->start( timer );
295 }
296 // ============================================================================
297 void TimingAuditor::after( CustomEventTypeRef evt, const std::string& name, const StatusCode& )
298 {
299  // Ignore obvious mistakes
300  if ( name.empty() && evt.empty() ) {
301  return;
302  }
303 
304  // look for the user timer in the map
305  std::string nick = name + ":" + evt;
306  auto found = m_mapUser.find( nick );
307 
308  // We cannot do much if the timer is not available
309  if ( m_mapUser.end() == found ) {
310  warning() << "Trying to stop the measure of the timing for '" << nick
311  << "' but it was never started. Check the code" << endmsg;
312  return;
313  }
314  m_timer->stop( found->second );
315 }
316 // ============================================================================
318 {
319  if ( IncidentType::BeginEvent == i.type() ) {
320  m_timer->start( m_map[m_appMgr.get()] );
321  ++m_indent;
322  m_inEvent = true;
323  } else if ( IncidentType::EndEvent == i.type() ) {
324  m_timer->stop( m_map[m_appMgr.get()] );
325  --m_indent;
326  m_inEvent = false;
327  }
328 }
329 // ============================================================================
330 // The END
331 // ============================================================================
void i_afterInitialize(INamedInterface *alg)
void i_beforeInitialize(INamedInterface *alg)
GaudiUtils::HashMap< std::string, int > m_mapUser
map used to record user timing events
TimingAuditor & operator=(const TimingAuditor &)=delete
virtual StatusCode finalize()
Definition: Auditor.cpp:200
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&#39;t already exist.
Definition: Auditor.h:109
const std::string & type() const
Access to the incident type.
Definition: Incident.h:41
Implementation of property with value of concrete type.
Definition: Property.h:314
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:299
virtual int addTimer(const std::string &name)=0
add a timer entry with the specified name
bool m_inEvent
"In event" flag
GaudiUtils::VectorMap< const INamedInterface *, int > m_map
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:84
StatusCode retrieveTool(const std::string &type, T *&tool, const IInterface *parent=nullptr, bool createIf=true)
Retrieve specified tool sub-type with tool dependent part of the name automatically assigned...
Definition: IToolSvc.h:146
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:36
STL class.
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
iterator end() const
"end" iterator for sequential access (const-only version!)
Definition: VectorMap.h:198
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
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:110
~TimingAuditor() override=default
destructor
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
virtual void addListener(IIncidentListener *lis, const std::string &type="", long priority=0, bool rethrow=false, bool singleShot=false)=0
Add listener.
Implements the time measurement inside a sequencer.
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:70
virtual void removeListener(IIncidentListener *lis, const std::string &type="")=0
Remove listener.
void handle(const Incident &) override
Inform that a new incident has occurred.
virtual double stop(int index)=0
stop the counter, return the elapsed time
Gaudi::Property< bool > m_goodForDOD
void before(StandardEventType, INamedInterface *) override
The following methods are meant to be implemented by the child class...
Definition: Auditor.cpp:73
const std::string & name() const override
Definition: Auditor.cpp:202
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
virtual const std::string & name() const =0
Retrieve the name of the instance.
evt
Definition: IOTest.py:85
void i_afterExecute(INamedInterface *alg)
Simple auditor which uses SequencerTimerTool for ALL algorithms, including the algorithm from main Ga...