]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliCodeTimer.cxx
New code to record the timing information of various methods in simulation and recons...
[u/mrichter/AliRoot.git] / STEER / AliCodeTimer.cxx
1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 *                                                                        *
4 * Author: The ALICE Off-line Project.                                    *
5 * Contributors are mentioned in the code where appropriate.              *
6 *                                                                        *
7 * Permission to use, copy, modify and distribute this software and its   *
8 * documentation strictly for non-commercial purposes is hereby granted   *
9 * without fee, provided that the above copyright notice appears in all   *
10 * copies and that both the copyright notice and this permission notice   *
11 * appear in the supporting documentation. The authors make no claims     *
12 * about the suitability of this software for any purpose. It is          *
13 * provided "as is" without express or implied warranty.                  *
14 **************************************************************************/
15
16 // $Id$
17
18 ///
19 /// Class to get organized with the way we're timing our methods...
20 ///
21 /// Typical usage is based on macros (like for AliLog related ones AliDebug...)
22 ///
23 /// The idea is to instrument the code with a few macro calls, and then,
24 /// at the end of the execution, get a printout of *all* the timers, by using
25 /// AliCodeTimer::Instance()->Print()
26 /// instead of getting scattered outputs all over the place.
27 ///
28 /// To time a given method, use :
29 ///
30 /// void ClassA::MethodA(....)
31 /// {
32 ///    AliCodeTimerAuto("")
33 /// }
34 ///
35 /// To get several timers within a same method, use : 
36 ///
37 /// void ClassA::MethodB(...)
38 /// {
39 ///   AliCodeTimerStart("doing something")
40 ///   ....
41 ///   AliCodeTimerStop("doing something")
42 ///
43 ///   AliCodeTimerStart("doing something else")
44 ///   ....
45 ///   AliCodeTimerStop("doing something else")
46 /// }
47 ///
48 ///
49
50 #include "AliCodeTimer.h"
51
52 #include <TMap.h>
53 #include <TObjString.h>
54 #include <TStopwatch.h>
55 #include <Riostream.h>
56
57 /// \cond CLASSIMP
58 ClassImp(AliCodeTimer)
59 ClassImp(AliCodeTimer::AliPair)
60 /// \endcond
61
62 AliCodeTimer* AliCodeTimer::fgInstance(0x0);
63
64 //_____________________________________________________________________________
65 void
66 AliCodeTimer::AliPair::Print(Option_t* opt) const
67 {
68   // Print timer information
69   cout << opt << Form("%s R:%.4fs C:%.4fs (%d slices)",
70                       Name().Data(),Timer()->RealTime(),
71                       Timer()->CpuTime(),Timer()->Counter()-1) << endl;
72 }
73
74
75 //_____________________________________________________________________________
76 AliCodeTimer::AliCodeTimer() : TObject(), fTimers(new TMap)
77 {
78   /// Ctor
79   fTimers->SetOwner(kTRUE);
80 }
81
82 //_____________________________________________________________________________
83 AliCodeTimer::~AliCodeTimer()
84 {
85   /// Dtor
86   Reset();
87   delete fTimers;
88 }
89
90 //_____________________________________________________________________________
91 AliCodeTimer*
92 AliCodeTimer::Instance()
93 {
94   // single instance of this class
95   if (!fgInstance) fgInstance = new AliCodeTimer;
96   return fgInstance;
97 }
98
99 //_____________________________________________________________________________
100 void AliCodeTimer::Continue(const char* classname, const char* methodname, 
101                             const char* message)
102 {
103   /// Resume a previously stop timer
104   TStopwatch* t = Stopwatch(classname,methodname,message);
105   if (t)
106   {
107     t->Continue();
108   }
109   else
110   {
111     AliError(Form("No timer for %s/%s/%s",classname,methodname,message));
112   }
113 }
114
115 //_____________________________________________________________________________
116 Double_t AliCodeTimer::CpuTime(const char* classname, 
117                                const char* methodname,
118                                const char* message) const
119 {
120   /// Return cpu time for a given timer
121   TStopwatch* t = Stopwatch(classname,methodname,message);
122   if (t)
123   {
124     return t->CpuTime();
125   }
126   else
127   {
128     return 0;
129   }
130 }
131
132 //_____________________________________________________________________________
133 TMap*
134 AliCodeTimer::MethodMap(const char* classname) const
135 {
136   /// Return the map for a given "classname"
137   return static_cast<TMap*>(fTimers->GetValue(classname));
138 }
139
140 //_____________________________________________________________________________
141 TObjArray*
142 AliCodeTimer::MessageArray(const char* classname, const char* methodname) const
143 {
144   /// Return the array for a given AliPair (classname,methodname)
145   TMap* m = MethodMap(classname);
146   if ( m ) 
147   {
148     return static_cast<TObjArray*>(m->GetValue(methodname));
149   }
150   return 0;
151 }
152
153 //_____________________________________________________________________________
154 void AliCodeTimer::PrintMethod(const char* classname, const char* methodname) const
155 {
156   /// Print all the timers for a given method
157   TObjArray* messages = MessageArray(classname,methodname);
158   messages->Sort();
159   
160   cout << "   " << methodname << " ";
161   
162   if ( messages->GetLast() == 0 ) 
163   {
164     AliPair* p = static_cast<AliPair*>(messages->First());
165     p->Print();
166   }
167   else
168   {
169     cout << endl;
170     
171     TIter next(messages);
172     AliPair* p;
173   
174     while ( ( p = static_cast<AliPair*>(next()) ) ) 
175     {
176       p->Print("        ");
177     }   
178   }
179 }
180
181 //_____________________________________________________________________________
182 void AliCodeTimer::PrintClass(const char* classname) const
183 {
184   /// Print all the timers for a given class
185   TMap* methods = MethodMap(classname);
186   TIter next(methods);
187   TObjString* methodname;
188   TObjArray methodNameArray;
189   
190   while ( ( methodname = static_cast<TObjString*>(next()) ) ) 
191   {
192     methodNameArray.Add(methodname);
193   }
194   
195   cout << classname << endl;
196   
197   methodNameArray.Sort();
198   
199   TIter mnext(&methodNameArray);
200   
201   while ( ( methodname = static_cast<TObjString*>(mnext()) ) ) 
202   {
203     PrintMethod(classname,methodname->String().Data());
204   }
205 }
206   
207 //_____________________________________________________________________________
208 void AliCodeTimer::Print(Option_t* /*opt*/) const
209 {
210   /// Print all the timers we hold
211   TIter next(fTimers);
212   TObjString* classname;
213   TObjArray classNameArray;
214   
215   while ( ( classname = static_cast<TObjString*>(next()) ) )
216   {
217     classNameArray.Add(classname);
218   }
219   
220   classNameArray.Sort();
221   
222   TIter cnext(&classNameArray);
223   while ( ( classname = static_cast<TObjString*>(cnext()) ) )
224   {
225     PrintClass(classname->String().Data());
226   }
227 }
228
229 //_____________________________________________________________________________
230 Double_t 
231 AliCodeTimer::RealTime(const char* classname, const char* methodname,
232                        const char* message) const
233 {
234   /// Return real time of a given time
235   TStopwatch* t = Stopwatch(classname,methodname,message);
236   if (t)
237   {
238     return t->RealTime();
239   }
240   else
241   {
242     return 0;
243   }
244 }
245
246 //_____________________________________________________________________________
247 void
248 AliCodeTimer::Reset()
249 {
250   /// Reset
251   TIter next(fTimers);
252   TObjString* classname;
253   
254   while ( ( classname = static_cast<TObjString*>(next()) ) ) 
255   {
256     TMap* m = static_cast<TMap*>(fTimers->GetValue(classname->String().Data()));
257     m->DeleteAll();
258   }
259   
260   fTimers->DeleteAll();
261 }
262
263 //_____________________________________________________________________________
264 void 
265 AliCodeTimer::Start(const char* classname, const char* methodname,
266                     const char* message)
267 {
268   /// Start a given time
269   TStopwatch* t = Stopwatch(classname,methodname,message);
270   if (!t)
271   {
272     TMap* m = MethodMap(classname);
273     if (!m)
274     {
275       m = new TMap;
276       m->SetOwner(kTRUE);
277       fTimers->Add(new TObjString(classname),m);
278     }      
279     TObjArray* messages = MessageArray(classname,methodname);
280     if (!messages)
281     {
282       messages = new TObjArray;
283       messages->SetOwner(kTRUE);
284       m->Add(new TObjString(methodname),messages);
285     }
286     t = new TStopwatch;
287     t->Start(kTRUE);
288     t->Stop();
289     messages->Add(new AliPair(new TObjString(message),t));
290   }
291   t->Start(kFALSE);
292 }
293
294 //_____________________________________________________________________________
295 void 
296 AliCodeTimer::Stop(const char* classname, const char* methodname,
297                    const char* message)
298 {
299   /// Stop a given timer
300   TStopwatch* t = Stopwatch(classname,methodname,message);
301   if (!t)
302   {
303     AliError(Form("No timer for %s/%s/%s",classname,methodname,message));
304   }
305   else
306   {
307     t->Stop();
308   }
309 }
310
311 //_____________________________________________________________________________
312 TStopwatch* 
313 AliCodeTimer::Stopwatch(const char* classname, const char* methodname,
314                         const char* message) const
315 {
316   /// Return the internal TStopwatch for a given timer
317   TObjArray* a = MessageArray(classname,methodname);
318   if ( a ) 
319   {
320     if (message)
321     {
322       TIter next(a);
323       AliPair* p;
324       while ( ( p = static_cast<AliPair*>(next()) ) ) 
325       {
326         TString s = p->Name();
327         if ( s == TString(message) ) 
328         {
329           return p->Timer();
330         }
331       }
332     }
333     else
334     {
335       return static_cast<TStopwatch*>(a->First());
336     }
337   }
338   return 0x0;
339 }