ROOT logo
/**************************************************************************
* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
*                                                                        *
* Author: The ALICE Off-line Project.                                    *
* Contributors are mentioned in the code where appropriate.              *
*                                                                        *
* Permission to use, copy, modify and distribute this software and its   *
* documentation strictly for non-commercial purposes is hereby granted   *
* without fee, provided that the above copyright notice appears in all   *
* copies and that both the copyright notice and this permission notice   *
* appear in the supporting documentation. The authors make no claims     *
* about the suitability of this software for any purpose. It is          *
* provided "as is" without express or implied warranty.                  *
**************************************************************************/
//  $Id$

//_________________________________________________________________________
// Class to get organized with the way we're timing our methods...
//
// Typical usage is based on macros (like for AliLog related ones AliDebug...)
//
// The idea is to instrument the code with a few macro calls, and then,
// at the end of the execution, get a printout of *all* the timers, by using
// AliCodeTimer::Instance()->Print()
// instead of getting scattered outputs all over the place.
//
// To time a given method, use :
//
// void ClassA::MethodA(....)
// {
//    AliCodeTimerAuto("")
// }
//
// To get several timers within a same method, use : 
//
// void ClassA::MethodB(...)
// {
//   AliCodeTimerStart("doing something")
//   ....
//   AliCodeTimerStop("doing something")
//
//   AliCodeTimerStart("doing something else")
//   ....
//   AliCodeTimerStop("doing something else")
// }

#include "AliCodeTimer.h"

#include <TMap.h>
#include <TObjString.h>
#include <TStopwatch.h>
#include <Riostream.h>

using std::endl;
using std::cout;
/// \cond CLASSIMP
ClassImp(AliCodeTimer)
ClassImp(AliCodeTimer::AliPair)
/// \endcond

AliCodeTimer* AliCodeTimer::fgInstance(0x0);

//_____________________________________________________________________________
void
AliCodeTimer::AliPair::Print(Option_t* opt) const
{
  // Print timer information
  cout << opt << Form("%s R:%.4fs C:%.4fs (%d slices)",
                      Name().Data(),Timer()->RealTime(),
                      Timer()->CpuTime(),Timer()->Counter()-1) << endl;
}


//_____________________________________________________________________________
AliCodeTimer::AliCodeTimer() : TObject(), fTimers(new TMap)
{
  /// Ctor
  fTimers->SetOwner(kTRUE);
}

//_____________________________________________________________________________
AliCodeTimer::~AliCodeTimer()
{
  /// Dtor
  Reset();
  delete fTimers;
}

//_____________________________________________________________________________
AliCodeTimer*
AliCodeTimer::Instance()
{
  // single instance of this class
  if (!fgInstance) fgInstance = new AliCodeTimer;
  return fgInstance;
}

//_____________________________________________________________________________
void AliCodeTimer::Continue(const char* classname, const char* methodname, 
                            const char* message)
{
  /// Resume a previously stop timer
  TStopwatch* t = Stopwatch(classname,methodname,message);
  if (t)
  {
    t->Continue();
  }
  else
  {
    AliError(Form("No timer for %s/%s/%s",classname,methodname,message));
  }
}

//_____________________________________________________________________________
Double_t AliCodeTimer::CpuTime(const char* classname, 
                               const char* methodname,
                               const char* message) const
{
  /// Return cpu time for a given timer
  TStopwatch* t = Stopwatch(classname,methodname,message);
  if (t)
  {
    return t->CpuTime();
  }
  else
  {
    return 0;
  }
}

//_____________________________________________________________________________
TMap*
AliCodeTimer::MethodMap(const char* classname) const
{
  /// Return the map for a given "classname"
  return static_cast<TMap*>(fTimers->GetValue(classname));
}

//_____________________________________________________________________________
TObjArray*
AliCodeTimer::MessageArray(const char* classname, const char* methodname) const
{
  /// Return the array for a given AliPair (classname,methodname)
  TMap* m = MethodMap(classname);
  if ( m ) 
  {
    return static_cast<TObjArray*>(m->GetValue(methodname));
  }
  return 0;
}

//_____________________________________________________________________________
void AliCodeTimer::PrintMethod(const char* classname, const char* methodname) const
{
  /// Print all the timers for a given method
  TObjArray* messages = MessageArray(classname,methodname);
  messages->Sort();
  
  cout << "   " << methodname << " ";
  
  if ( messages->GetLast() == 0 ) 
  {
    AliPair* p = static_cast<AliPair*>(messages->First());
    p->Print();
  }
  else
  {
    cout << endl;
    
    TIter next(messages);
    AliPair* p;
  
    while ( ( p = static_cast<AliPair*>(next()) ) ) 
    {
      p->Print("        ");
    }   
  }
}

//_____________________________________________________________________________
void AliCodeTimer::PrintClass(const char* classname) const
{
  /// Print all the timers for a given class
  TMap* methods = MethodMap(classname);
  TIter next(methods);
  TObjString* methodname;
  TObjArray methodNameArray;
  
  while ( ( methodname = static_cast<TObjString*>(next()) ) ) 
  {
    methodNameArray.Add(methodname);
  }
  
  cout << classname << endl;
  
  methodNameArray.Sort();
  
  TIter mnext(&methodNameArray);
  
  while ( ( methodname = static_cast<TObjString*>(mnext()) ) ) 
  {
    PrintMethod(classname,methodname->String().Data());
  }
}
  
//_____________________________________________________________________________
void AliCodeTimer::Print(Option_t* /*opt*/) const
{
  /// Print all the timers we hold
  TIter next(fTimers);
  TObjString* classname;
  TObjArray classNameArray;
  
  while ( ( classname = static_cast<TObjString*>(next()) ) )
  {
    classNameArray.Add(classname);
  }
  
  classNameArray.Sort();
  
  TIter cnext(&classNameArray);
  while ( ( classname = static_cast<TObjString*>(cnext()) ) )
  {
    PrintClass(classname->String().Data());
  }
}

//_____________________________________________________________________________
Double_t 
AliCodeTimer::RealTime(const char* classname, const char* methodname,
                       const char* message) const
{
  /// Return real time of a given time
  TStopwatch* t = Stopwatch(classname,methodname,message);
  if (t)
  {
    return t->RealTime();
  }
  else
  {
    return 0;
  }
}

//_____________________________________________________________________________
void
AliCodeTimer::Reset()
{
  /// Reset
  TIter next(fTimers);
  TObjString* classname;
  
  while ( ( classname = static_cast<TObjString*>(next()) ) ) 
  {
    TMap* m = static_cast<TMap*>(fTimers->GetValue(classname->String().Data()));
    m->DeleteAll();
  }
  
  fTimers->DeleteAll();
}

//_____________________________________________________________________________
void 
AliCodeTimer::Start(const char* classname, const char* methodname,
                    const char* message)
{
  /// Start a given time
  TStopwatch* t = Stopwatch(classname,methodname,message);
  if (!t)
  {
    TMap* m = MethodMap(classname);
    if (!m)
    {
      m = new TMap;
      m->SetOwner(kTRUE);
      fTimers->Add(new TObjString(classname),m);
    }      
    TObjArray* messages = MessageArray(classname,methodname);
    if (!messages)
    {
      messages = new TObjArray;
      messages->SetOwner(kTRUE);
      m->Add(new TObjString(methodname),messages);
    }
    t = new TStopwatch;
    t->Start(kTRUE);
    t->Stop();
    messages->Add(new AliPair(new TObjString(message),t));
  }
  t->Start(kFALSE);
}

//_____________________________________________________________________________
void 
AliCodeTimer::Stop(const char* classname, const char* methodname,
                   const char* message)
{
  /// Stop a given timer
  TStopwatch* t = Stopwatch(classname,methodname,message);
  if (!t)
  {
    AliError(Form("No timer for %s/%s/%s",classname,methodname,message));
  }
  else
  {
    t->Stop();
  }
}

//_____________________________________________________________________________
TStopwatch* 
AliCodeTimer::Stopwatch(const char* classname, const char* methodname,
                        const char* message) const
{
  /// Return the internal TStopwatch for a given timer
  TObjArray* a = MessageArray(classname,methodname);
  if ( a ) 
  {
    if (message)
    {
      TIter next(a);
      AliPair* p;
      while ( ( p = static_cast<AliPair*>(next()) ) ) 
      {
        TString s = p->Name();
        if ( s == TString(message) ) 
        {
          return p->Timer();
        }
      }
    }
    else
    {
      return static_cast<TStopwatch*>(a->First());
    }
  }
  return 0x0;
}
 AliCodeTimer.cxx:1
 AliCodeTimer.cxx:2
 AliCodeTimer.cxx:3
 AliCodeTimer.cxx:4
 AliCodeTimer.cxx:5
 AliCodeTimer.cxx:6
 AliCodeTimer.cxx:7
 AliCodeTimer.cxx:8
 AliCodeTimer.cxx:9
 AliCodeTimer.cxx:10
 AliCodeTimer.cxx:11
 AliCodeTimer.cxx:12
 AliCodeTimer.cxx:13
 AliCodeTimer.cxx:14
 AliCodeTimer.cxx:15
 AliCodeTimer.cxx:16
 AliCodeTimer.cxx:17
 AliCodeTimer.cxx:18
 AliCodeTimer.cxx:19
 AliCodeTimer.cxx:20
 AliCodeTimer.cxx:21
 AliCodeTimer.cxx:22
 AliCodeTimer.cxx:23
 AliCodeTimer.cxx:24
 AliCodeTimer.cxx:25
 AliCodeTimer.cxx:26
 AliCodeTimer.cxx:27
 AliCodeTimer.cxx:28
 AliCodeTimer.cxx:29
 AliCodeTimer.cxx:30
 AliCodeTimer.cxx:31
 AliCodeTimer.cxx:32
 AliCodeTimer.cxx:33
 AliCodeTimer.cxx:34
 AliCodeTimer.cxx:35
 AliCodeTimer.cxx:36
 AliCodeTimer.cxx:37
 AliCodeTimer.cxx:38
 AliCodeTimer.cxx:39
 AliCodeTimer.cxx:40
 AliCodeTimer.cxx:41
 AliCodeTimer.cxx:42
 AliCodeTimer.cxx:43
 AliCodeTimer.cxx:44
 AliCodeTimer.cxx:45
 AliCodeTimer.cxx:46
 AliCodeTimer.cxx:47
 AliCodeTimer.cxx:48
 AliCodeTimer.cxx:49
 AliCodeTimer.cxx:50
 AliCodeTimer.cxx:51
 AliCodeTimer.cxx:52
 AliCodeTimer.cxx:53
 AliCodeTimer.cxx:54
 AliCodeTimer.cxx:55
 AliCodeTimer.cxx:56
 AliCodeTimer.cxx:57
 AliCodeTimer.cxx:58
 AliCodeTimer.cxx:59
 AliCodeTimer.cxx:60
 AliCodeTimer.cxx:61
 AliCodeTimer.cxx:62
 AliCodeTimer.cxx:63
 AliCodeTimer.cxx:64
 AliCodeTimer.cxx:65
 AliCodeTimer.cxx:66
 AliCodeTimer.cxx:67
 AliCodeTimer.cxx:68
 AliCodeTimer.cxx:69
 AliCodeTimer.cxx:70
 AliCodeTimer.cxx:71
 AliCodeTimer.cxx:72
 AliCodeTimer.cxx:73
 AliCodeTimer.cxx:74
 AliCodeTimer.cxx:75
 AliCodeTimer.cxx:76
 AliCodeTimer.cxx:77
 AliCodeTimer.cxx:78
 AliCodeTimer.cxx:79
 AliCodeTimer.cxx:80
 AliCodeTimer.cxx:81
 AliCodeTimer.cxx:82
 AliCodeTimer.cxx:83
 AliCodeTimer.cxx:84
 AliCodeTimer.cxx:85
 AliCodeTimer.cxx:86
 AliCodeTimer.cxx:87
 AliCodeTimer.cxx:88
 AliCodeTimer.cxx:89
 AliCodeTimer.cxx:90
 AliCodeTimer.cxx:91
 AliCodeTimer.cxx:92
 AliCodeTimer.cxx:93
 AliCodeTimer.cxx:94
 AliCodeTimer.cxx:95
 AliCodeTimer.cxx:96
 AliCodeTimer.cxx:97
 AliCodeTimer.cxx:98
 AliCodeTimer.cxx:99
 AliCodeTimer.cxx:100
 AliCodeTimer.cxx:101
 AliCodeTimer.cxx:102
 AliCodeTimer.cxx:103
 AliCodeTimer.cxx:104
 AliCodeTimer.cxx:105
 AliCodeTimer.cxx:106
 AliCodeTimer.cxx:107
 AliCodeTimer.cxx:108
 AliCodeTimer.cxx:109
 AliCodeTimer.cxx:110
 AliCodeTimer.cxx:111
 AliCodeTimer.cxx:112
 AliCodeTimer.cxx:113
 AliCodeTimer.cxx:114
 AliCodeTimer.cxx:115
 AliCodeTimer.cxx:116
 AliCodeTimer.cxx:117
 AliCodeTimer.cxx:118
 AliCodeTimer.cxx:119
 AliCodeTimer.cxx:120
 AliCodeTimer.cxx:121
 AliCodeTimer.cxx:122
 AliCodeTimer.cxx:123
 AliCodeTimer.cxx:124
 AliCodeTimer.cxx:125
 AliCodeTimer.cxx:126
 AliCodeTimer.cxx:127
 AliCodeTimer.cxx:128
 AliCodeTimer.cxx:129
 AliCodeTimer.cxx:130
 AliCodeTimer.cxx:131
 AliCodeTimer.cxx:132
 AliCodeTimer.cxx:133
 AliCodeTimer.cxx:134
 AliCodeTimer.cxx:135
 AliCodeTimer.cxx:136
 AliCodeTimer.cxx:137
 AliCodeTimer.cxx:138
 AliCodeTimer.cxx:139
 AliCodeTimer.cxx:140
 AliCodeTimer.cxx:141
 AliCodeTimer.cxx:142
 AliCodeTimer.cxx:143
 AliCodeTimer.cxx:144
 AliCodeTimer.cxx:145
 AliCodeTimer.cxx:146
 AliCodeTimer.cxx:147
 AliCodeTimer.cxx:148
 AliCodeTimer.cxx:149
 AliCodeTimer.cxx:150
 AliCodeTimer.cxx:151
 AliCodeTimer.cxx:152
 AliCodeTimer.cxx:153
 AliCodeTimer.cxx:154
 AliCodeTimer.cxx:155
 AliCodeTimer.cxx:156
 AliCodeTimer.cxx:157
 AliCodeTimer.cxx:158
 AliCodeTimer.cxx:159
 AliCodeTimer.cxx:160
 AliCodeTimer.cxx:161
 AliCodeTimer.cxx:162
 AliCodeTimer.cxx:163
 AliCodeTimer.cxx:164
 AliCodeTimer.cxx:165
 AliCodeTimer.cxx:166
 AliCodeTimer.cxx:167
 AliCodeTimer.cxx:168
 AliCodeTimer.cxx:169
 AliCodeTimer.cxx:170
 AliCodeTimer.cxx:171
 AliCodeTimer.cxx:172
 AliCodeTimer.cxx:173
 AliCodeTimer.cxx:174
 AliCodeTimer.cxx:175
 AliCodeTimer.cxx:176
 AliCodeTimer.cxx:177
 AliCodeTimer.cxx:178
 AliCodeTimer.cxx:179
 AliCodeTimer.cxx:180
 AliCodeTimer.cxx:181
 AliCodeTimer.cxx:182
 AliCodeTimer.cxx:183
 AliCodeTimer.cxx:184
 AliCodeTimer.cxx:185
 AliCodeTimer.cxx:186
 AliCodeTimer.cxx:187
 AliCodeTimer.cxx:188
 AliCodeTimer.cxx:189
 AliCodeTimer.cxx:190
 AliCodeTimer.cxx:191
 AliCodeTimer.cxx:192
 AliCodeTimer.cxx:193
 AliCodeTimer.cxx:194
 AliCodeTimer.cxx:195
 AliCodeTimer.cxx:196
 AliCodeTimer.cxx:197
 AliCodeTimer.cxx:198
 AliCodeTimer.cxx:199
 AliCodeTimer.cxx:200
 AliCodeTimer.cxx:201
 AliCodeTimer.cxx:202
 AliCodeTimer.cxx:203
 AliCodeTimer.cxx:204
 AliCodeTimer.cxx:205
 AliCodeTimer.cxx:206
 AliCodeTimer.cxx:207
 AliCodeTimer.cxx:208
 AliCodeTimer.cxx:209
 AliCodeTimer.cxx:210
 AliCodeTimer.cxx:211
 AliCodeTimer.cxx:212
 AliCodeTimer.cxx:213
 AliCodeTimer.cxx:214
 AliCodeTimer.cxx:215
 AliCodeTimer.cxx:216
 AliCodeTimer.cxx:217
 AliCodeTimer.cxx:218
 AliCodeTimer.cxx:219
 AliCodeTimer.cxx:220
 AliCodeTimer.cxx:221
 AliCodeTimer.cxx:222
 AliCodeTimer.cxx:223
 AliCodeTimer.cxx:224
 AliCodeTimer.cxx:225
 AliCodeTimer.cxx:226
 AliCodeTimer.cxx:227
 AliCodeTimer.cxx:228
 AliCodeTimer.cxx:229
 AliCodeTimer.cxx:230
 AliCodeTimer.cxx:231
 AliCodeTimer.cxx:232
 AliCodeTimer.cxx:233
 AliCodeTimer.cxx:234
 AliCodeTimer.cxx:235
 AliCodeTimer.cxx:236
 AliCodeTimer.cxx:237
 AliCodeTimer.cxx:238
 AliCodeTimer.cxx:239
 AliCodeTimer.cxx:240
 AliCodeTimer.cxx:241
 AliCodeTimer.cxx:242
 AliCodeTimer.cxx:243
 AliCodeTimer.cxx:244
 AliCodeTimer.cxx:245
 AliCodeTimer.cxx:246
 AliCodeTimer.cxx:247
 AliCodeTimer.cxx:248
 AliCodeTimer.cxx:249
 AliCodeTimer.cxx:250
 AliCodeTimer.cxx:251
 AliCodeTimer.cxx:252
 AliCodeTimer.cxx:253
 AliCodeTimer.cxx:254
 AliCodeTimer.cxx:255
 AliCodeTimer.cxx:256
 AliCodeTimer.cxx:257
 AliCodeTimer.cxx:258
 AliCodeTimer.cxx:259
 AliCodeTimer.cxx:260
 AliCodeTimer.cxx:261
 AliCodeTimer.cxx:262
 AliCodeTimer.cxx:263
 AliCodeTimer.cxx:264
 AliCodeTimer.cxx:265
 AliCodeTimer.cxx:266
 AliCodeTimer.cxx:267
 AliCodeTimer.cxx:268
 AliCodeTimer.cxx:269
 AliCodeTimer.cxx:270
 AliCodeTimer.cxx:271
 AliCodeTimer.cxx:272
 AliCodeTimer.cxx:273
 AliCodeTimer.cxx:274
 AliCodeTimer.cxx:275
 AliCodeTimer.cxx:276
 AliCodeTimer.cxx:277
 AliCodeTimer.cxx:278
 AliCodeTimer.cxx:279
 AliCodeTimer.cxx:280
 AliCodeTimer.cxx:281
 AliCodeTimer.cxx:282
 AliCodeTimer.cxx:283
 AliCodeTimer.cxx:284
 AliCodeTimer.cxx:285
 AliCodeTimer.cxx:286
 AliCodeTimer.cxx:287
 AliCodeTimer.cxx:288
 AliCodeTimer.cxx:289
 AliCodeTimer.cxx:290
 AliCodeTimer.cxx:291
 AliCodeTimer.cxx:292
 AliCodeTimer.cxx:293
 AliCodeTimer.cxx:294
 AliCodeTimer.cxx:295
 AliCodeTimer.cxx:296
 AliCodeTimer.cxx:297
 AliCodeTimer.cxx:298
 AliCodeTimer.cxx:299
 AliCodeTimer.cxx:300
 AliCodeTimer.cxx:301
 AliCodeTimer.cxx:302
 AliCodeTimer.cxx:303
 AliCodeTimer.cxx:304
 AliCodeTimer.cxx:305
 AliCodeTimer.cxx:306
 AliCodeTimer.cxx:307
 AliCodeTimer.cxx:308
 AliCodeTimer.cxx:309
 AliCodeTimer.cxx:310
 AliCodeTimer.cxx:311
 AliCodeTimer.cxx:312
 AliCodeTimer.cxx:313
 AliCodeTimer.cxx:314
 AliCodeTimer.cxx:315
 AliCodeTimer.cxx:316
 AliCodeTimer.cxx:317
 AliCodeTimer.cxx:318
 AliCodeTimer.cxx:319
 AliCodeTimer.cxx:320
 AliCodeTimer.cxx:321
 AliCodeTimer.cxx:322
 AliCodeTimer.cxx:323
 AliCodeTimer.cxx:324
 AliCodeTimer.cxx:325
 AliCodeTimer.cxx:326
 AliCodeTimer.cxx:327
 AliCodeTimer.cxx:328
 AliCodeTimer.cxx:329
 AliCodeTimer.cxx:330
 AliCodeTimer.cxx:331
 AliCodeTimer.cxx:332
 AliCodeTimer.cxx:333
 AliCodeTimer.cxx:334
 AliCodeTimer.cxx:335
 AliCodeTimer.cxx:336
 AliCodeTimer.cxx:337
 AliCodeTimer.cxx:338