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