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/IToolSvc.h"
3 #include "GaudiKernel/IIncidentListener.h"
4 #include "GaudiKernel/IIncidentSvc.h"
5 #include "GaudiKernel/IToolSvc.h"
6 #include "GaudiKernel/VectorMap.h"
7 #include "GaudiKernel/HashMap.h"
8 #include "GaudiKernel/MsgStream.h"
9 // ============================================================================
10 // GaudiAlg
11 // ============================================================================
12 #include "GaudiAlg/ISequencerTimerTool.h"
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 extends1<Auditor, IIncidentListener> {
29 public:
30 
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:
56  TimingAuditor ( const std::string& name, ISvcLocator* pSvc )
57  : base_class ( name , pSvc )
58  {
59  declareProperty ( "OptimizedForDOD" , m_goodForDOD ) ;
60  }
62  ~TimingAuditor() override = default;
63 
64  // delete default/copy constructor and assignment
65  TimingAuditor () = delete;
66  TimingAuditor ( const TimingAuditor& ) = delete ;
67  TimingAuditor& operator=( const TimingAuditor& ) = delete ;
68 private:
69  // tool service
71  // incident service
73  // the timer tool
75  // ApplicationManager
77  //
79  // indentation level
80  int m_indent = 0 ;
81  // "in event"
82  bool m_inEvent = false ;
83  // "optimized for Data-On-Demand Service"
84  bool m_goodForDOD = false ;
85  //
87 
88  // Whether the timing has been saved already
89  bool m_histoSaved = false ;
90 
91 
92 } ;
93 // ============================================================================
95 // ============================================================================
97 // ============================================================================
99 {
101  if ( sc.isFailure() ) { return sc ; } // RETURN
102 
103  MsgStream log ( msgSvc() , name() ) ;
104 
105  // get tool service
106  if ( ! m_toolSvc )
107  {
108  m_toolSvc = Auditor::service ( "ToolSvc" );
109  if ( !m_toolSvc )
110  {
111  log << "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  log << MSG::ERROR
121  << "Could not retrieve ISequencerTimerTool" << endmsg ;
122  return sc ;
123  }
124  }
125  }
126  // get incident service
127  if ( !m_incSvc )
128  {
129  m_incSvc = Auditor::service ( "IncidentSvc" );
130  if ( !m_incSvc )
131  {
132  log << MSG::ERROR
133  << "Could not retrieve 'IncidentSvc'" << endmsg ;
134  return StatusCode::FAILURE ;
135  }
136  m_incSvc -> addListener ( this , IncidentType::BeginEvent ) ;
137  m_incSvc -> addListener ( this , IncidentType::EndEvent ) ;
138  }
139  // get the application manager
140  if ( !m_appMgr )
141  {
142  m_appMgr = Auditor::service ( "ApplicationMgr" );
143  if ( !m_appMgr )
144  {
145  log << MSG::ERROR
146  << "Could not retrieve 'ApplicationMgr'" << endmsg ;
147  return sc ;
148  }
149  if ( m_map.end() == m_map.find( m_appMgr.get() ) )
150  {
151  m_map.insert ( m_appMgr.get() , m_timer->addTimer( "EVENT LOOP" ) ) ;
152  }
153  }
154  //
155  return StatusCode::SUCCESS ;
156 }
157 // ============================================================================
159 {
160  if ( m_incSvc )
161  {
162  m_incSvc -> removeListener ( this , IncidentType::BeginEvent ) ;
163  m_incSvc -> removeListener ( this , IncidentType::EndEvent ) ;
164  m_incSvc.reset();
165  }
166  if ( m_toolSvc )
167  {
168  // the 2 following line are commented out: it is
169  // is a temporary hack which prevent a crash due to a problem in
170  // the reference counting
171  // if ( 0 != m_timer )
172  // { m_toolSvc -> releaseTool ( m_timer ) . ignore() ; m_timer = 0 ; }
173  m_toolSvc.reset();
174  }
175  m_appMgr.reset();
176  // clear the map
177  m_map.clear() ;
178  // finalize the base class
179  return Auditor::finalize () ;
180 }
181 // ============================================================================
182 void TimingAuditor::before(StandardEventType evt, INamedInterface *alg)
183 {
184  switch (evt) {
185  case IAuditor::Initialize : i_beforeInitialize( alg ); break;
186  case IAuditor::Execute : i_beforeExecute( alg ); break;
187  case IAuditor::Finalize : i_beforeFinalize( alg ); break;
188  default: break;
189  }
190 }
191 // ============================================================================
192 void TimingAuditor::after(StandardEventType evt, INamedInterface *alg, const StatusCode &)
193 {
194  switch (evt) {
195  case IAuditor::Initialize : i_afterInitialize( alg ); break;
196  case IAuditor::Execute : i_afterExecute( alg ); break;
197  default: break;
198  }
199 }
200 // ============================================================================
202 {
203  if (!m_histoSaved)
204  {
206  m_histoSaved = true;
207  }
208 }
209 
210 // ============================================================================
212 {
213  if ( m_goodForDOD ) { return ; }
214  //
215  if ( !alg ) { return ; }
216  auto found = m_map.find( alg ) ;
217  if ( m_map.end() != found ) { return ; }
218  ++m_indent ;
219  std::string nick = alg->name() ;
220  if ( 0 < m_indent ) { nick = std::string ( m_indent , ' ') + nick ; }
221  if ( m_inEvent )
222  {
223  nick[0] = '*' ;
224  MsgStream log( msgSvc() , name() ) ;
225  log << MSG::DEBUG
226  << "Insert non-structural component '"
227  << alg->name() << "' of type '"
228  << System::typeinfoName(typeid(*alg)) << "' at level "
229  << m_indent << endmsg ;
230  }
231  int timer = m_timer->addTimer( nick ) ;
232  m_map.insert ( alg , timer ) ;
233  m_timer->start( timer ) ;
234 }
235 // ============================================================================
237 {
238  if ( m_goodForDOD || !alg ) { return ; }
239  --m_indent ;
240 }
241 // ============================================================================
243 {
244  if ( !alg ) { return ; }
245  ++m_indent ;
246  auto found = m_map.find( alg ) ;
247  if ( m_map.end() == found )
248  {
249  MsgStream log( msgSvc() , name() ) ;
250  log << MSG::DEBUG
251  << "Insert non-structural component '"
252  << alg->name() << "' of type '"
253  << System::typeinfoName(typeid(*alg)) << "' at level "
254  << m_indent << endmsg ;
255  std::string nick = alg->name() ;
256  if ( 0 < m_indent ) { nick = std::string ( m_indent , ' ') + nick ; }
257  if ( !m_goodForDOD ) { nick[0]='*' ;}
258  int timer = m_timer->addTimer( nick ) ;
259  m_map.insert ( alg , timer ) ;
260  m_timer->start( timer ) ;
261  return ;
262  }
263  m_timer->start( found->second ) ;
264 }
265 // ============================================================================
267 {
268  if ( !alg ) { return ; }
269  auto found = m_map.find( alg ) ;
270  if ( m_map.end() == found ) { return ; }
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() ) { return; }
279 
280  // look for the user timer in the map
281  int timer = 0;
282  std::string nick = name + ":" + evt;
283  auto found = m_mapUser.find( nick );
284 
285  if ( m_mapUser.end() == found ) {
286  // add a new timer if not yet available
287  timer = m_timer->addTimer( nick ) ;
288  m_mapUser[nick] = timer;
289  } else {
290  timer = found->second;
291  }
292  m_timer->start( timer );
293 }
294 // ============================================================================
295 void TimingAuditor::after(CustomEventTypeRef evt, const std::string& name, const StatusCode &)
296 {
297  // Ignore obvious mistakes
298  if ( name.empty() && evt.empty() ) { return; }
299 
300  // look for the user timer in the map
301  std::string nick = name + ":" + evt;
302  auto found = m_mapUser.find( nick );
303 
304  // We cannot do much if the timer is not available
305  if ( m_mapUser.end() == found ) {
306  MsgStream log(msgSvc(), this->name());
307  log << MSG::WARNING << "Trying to stop the measure of the timing for '"
308  << nick << "' but it was never started. Check the code"
309  << endmsg;
310  return;
311  }
312  m_timer->stop( found->second );
313 }
314 // ============================================================================
316 {
317  if ( IncidentType::BeginEvent == i.type () ) {
318  m_timer -> start ( m_map[ m_appMgr.get() ] ) ;
319  ++m_indent ;
320  m_inEvent = true ;
321  } else if ( IncidentType::EndEvent == i.type () ) {
322  m_timer -> stop ( m_map[ m_appMgr.get() ] ) ;
323  --m_indent ;
324  m_inEvent = false ;
325  }
326 }
327 // ============================================================================
328 // The END
329 // ============================================================================
void i_afterInitialize(INamedInterface *alg)
void i_beforeInitialize(INamedInterface *alg)
Definition of the MsgStream class used to transmit messages.
Definition: MsgStream.h:24
TimingAuditor & operator=(const TimingAuditor &)=delete
virtual StatusCode finalize()
Definition: Auditor.cpp:207
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:119
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
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:244
const std::string & type() const
Access to the incident type.
Definition: Incident.h:34
TimingAuditor(const std::string &name, ISvcLocator *pSvc)
standard constructor
virtual int addTimer(const std::string &name)=0
add a timer entry with the specified name
bool m_inEvent
"In event" flag
GAUDI_API const std::string typeinfoName(const std::type_info &)
Get platform independent information about the class type.
Definition: System.cpp:297
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
virtual const std::string & name() const =0
Retrieve the name of the instance.
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
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.
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:26
SmartIF< IIncidentSvc > m_incSvc
incident service
#define DECLARE_COMPONENT(type)
Definition: PluginService.h:36
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:116
~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
Base class used to extend a class implementing other interfaces.
Definition: extends.h:10
Base class for all Incidents (computing events).
Definition: Incident.h:16
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:91
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:96
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...