/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TBenchmark.h"
#include "TROOT.h"
#include "TStopwatch.h"


TBenchmark *gBenchmark = 0;

ClassImp(TBenchmark)

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TBenchmark                                                           //
//                                                                      //
// This class is a ROOT utility to help benchmarking applications       //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

//______________________________________________________________________________
TBenchmark::TBenchmark(): TNamed()
{
   // Benchmark default constructor

   fNbench   = 0;
   fNmax     = 20;
   fNames    = 0;
   fRealTime = 0;
   fCpuTime  = 0;
   fTimer    = 0;
}

//______________________________________________________________________________
TBenchmark::TBenchmark(const TBenchmark& bm) :
  TNamed(bm),
  fNbench(bm.fNbench),
  fNmax(bm.fNmax),
  fNames(0),
  fRealTime(0),
  fCpuTime(0),
  fTimer(0)
{
   // Copy constructor.

   fNames    = new TString[fNmax];
   fRealTime = new Float_t[fNmax];
   fCpuTime  = new Float_t[fNmax];
   fTimer    = new TStopwatch[fNmax];

   for(Int_t i = 0; i<fNmax; ++i) {
      fNames[i] = bm.fNames[i];
      fRealTime[i] = bm.fRealTime[i];
      fCpuTime[i] = bm.fCpuTime[i];
      fTimer[i] = bm.fTimer[i];
   }
}

//______________________________________________________________________________
TBenchmark& TBenchmark::operator=(const TBenchmark& bm)
{
   // Assignment operator.

   if (this!=&bm) {
      TNamed::operator=(bm);
      fNbench=bm.fNbench;
      fNmax=bm.fNmax;

      delete [] fNames;
      delete [] fRealTime;
      delete [] fCpuTime;
      delete [] fTimer;

      fNames    = new TString[fNmax];
      fRealTime = new Float_t[fNmax];
      fCpuTime  = new Float_t[fNmax];
      fTimer    = new TStopwatch[fNmax];

      for(Int_t i = 0; i<fNmax; ++i) {
         fNames[i] = bm.fNames[i];
         fRealTime[i] = bm.fRealTime[i];
         fCpuTime[i] = bm.fCpuTime[i];
         fTimer[i] = bm.fTimer[i];
      }
   }
   return *this;
}

//______________________________________________________________________________
TBenchmark::~TBenchmark()
{
   // Benchmark destructor.

   fNbench   = 0;
   if (fNames)    { delete [] fNames;    fNames  = 0;}
   if (fRealTime) { delete [] fRealTime; fRealTime  = 0;}
   if (fCpuTime)  { delete [] fCpuTime;  fCpuTime  = 0;}
   if (fTimer  )  { delete [] fTimer;    fTimer  = 0;}
}

//______________________________________________________________________________
Int_t TBenchmark::GetBench(const char *name) const
{
   // Returns index of Benchmark name.

   for (Int_t i=0;i<fNbench;i++) {
      if (!strcmp(name,(const char*)fNames[i])) return i;
   }
   return -1;
}

//______________________________________________________________________________
Float_t TBenchmark::GetCpuTime(const char *name)
{
   // Returns Cpu time used by Benchmark name.

   Int_t bench = GetBench(name);
   if (bench >= 0) return fCpuTime[bench];
   else            return 0;
}

//______________________________________________________________________________
Float_t TBenchmark::GetRealTime(const char *name)
{
   // Returns Realtime used by Benchmark name.

   Int_t bench = GetBench(name);
   if (bench >= 0) return fRealTime[bench];
   else            return 0;
}

//______________________________________________________________________________
void TBenchmark::Print(const char *name) const
{
   // Prints parameters of Benchmark name.

   Int_t bench = GetBench(name);
   if (bench < 0) return;
   Printf("%-10s: Real Time = %6.2f seconds Cpu Time = %6.2f seconds",name,fRealTime[bench],fCpuTime[bench]);
}

//______________________________________________________________________________
void TBenchmark::Reset()
{
   // Reset all Benchmarks

   fNbench = 0;
}

//______________________________________________________________________________
void TBenchmark::Show(const char *name)
{
   // Stops Benchmark name and Prints results

   Stop(name);
   Print((char*)name);
}

//______________________________________________________________________________
void TBenchmark::Start(const char *name)
{
   // Starts Benchmark with the specified name.
   //
   // An independent timer (see class TStopwatch) is started.
   // The name of the benchmark is entered into the list of benchmarks.
   // Benchmark can be stopped via TBenchmark::Stop().
   // Results can be printed via TBenchmark::Print().
   // TBenchmark::Show() can be used to stop benchmark and print results.
   // If name is an already existing benchmark, timing will resume.
   // A summary of all benchmarks can be seen via TBenchmark::Summary().

   if (!fNames) {
      fNames    = new TString[fNmax];
      fRealTime = new Float_t[fNmax];
      fCpuTime  = new Float_t[fNmax];
      fTimer    = new TStopwatch[fNmax];
   }
   Int_t bench = GetBench(name);
   if (bench < 0 && fNbench < fNmax ) {
      // define a new benchmark to Start
      fNames[fNbench] = name;
      bench = fNbench;
      fNbench++;
      fTimer[bench].Reset();
      fTimer[bench].Start();
      fRealTime[bench] = 0;
      fCpuTime[bench]  = 0;
   } else if (bench >= 0) {
      // Resume the existing benchmark
      fTimer[bench].Continue();
   }
   else
      Warning("Start","too many benchemarks");
}

//______________________________________________________________________________
void TBenchmark::Stop(const char *name)
{
   // Terminates Benchmark with specified name.

   Int_t bench = GetBench(name);
   if (bench < 0) return;

   fTimer[bench].Stop();
   fRealTime[bench] = fTimer[bench].RealTime();
   fCpuTime[bench]  = fTimer[bench].CpuTime();
}

//______________________________________________________________________________
void TBenchmark::Summary(Float_t &rt, Float_t &cp)
{
   // Prints a summary of all benchmarks.

   rt = 0;
   cp = 0;
   for (Int_t i=0;i<fNbench;i++) {
      Printf("%-10s: Real Time = %6.2f seconds Cpu Time = %6.2f seconds",(const char*)fNames[i],fRealTime[i],fCpuTime[i]);
      rt += fRealTime[i];
      cp += fCpuTime[i];
   }
   Printf("%-10s: Real Time = %6.2f seconds Cpu Time = %6.2f seconds","TOTAL",rt,cp);
}
 TBenchmark.cxx:1
 TBenchmark.cxx:2
 TBenchmark.cxx:3
 TBenchmark.cxx:4
 TBenchmark.cxx:5
 TBenchmark.cxx:6
 TBenchmark.cxx:7
 TBenchmark.cxx:8
 TBenchmark.cxx:9
 TBenchmark.cxx:10
 TBenchmark.cxx:11
 TBenchmark.cxx:12
 TBenchmark.cxx:13
 TBenchmark.cxx:14
 TBenchmark.cxx:15
 TBenchmark.cxx:16
 TBenchmark.cxx:17
 TBenchmark.cxx:18
 TBenchmark.cxx:19
 TBenchmark.cxx:20
 TBenchmark.cxx:21
 TBenchmark.cxx:22
 TBenchmark.cxx:23
 TBenchmark.cxx:24
 TBenchmark.cxx:25
 TBenchmark.cxx:26
 TBenchmark.cxx:27
 TBenchmark.cxx:28
 TBenchmark.cxx:29
 TBenchmark.cxx:30
 TBenchmark.cxx:31
 TBenchmark.cxx:32
 TBenchmark.cxx:33
 TBenchmark.cxx:34
 TBenchmark.cxx:35
 TBenchmark.cxx:36
 TBenchmark.cxx:37
 TBenchmark.cxx:38
 TBenchmark.cxx:39
 TBenchmark.cxx:40
 TBenchmark.cxx:41
 TBenchmark.cxx:42
 TBenchmark.cxx:43
 TBenchmark.cxx:44
 TBenchmark.cxx:45
 TBenchmark.cxx:46
 TBenchmark.cxx:47
 TBenchmark.cxx:48
 TBenchmark.cxx:49
 TBenchmark.cxx:50
 TBenchmark.cxx:51
 TBenchmark.cxx:52
 TBenchmark.cxx:53
 TBenchmark.cxx:54
 TBenchmark.cxx:55
 TBenchmark.cxx:56
 TBenchmark.cxx:57
 TBenchmark.cxx:58
 TBenchmark.cxx:59
 TBenchmark.cxx:60
 TBenchmark.cxx:61
 TBenchmark.cxx:62
 TBenchmark.cxx:63
 TBenchmark.cxx:64
 TBenchmark.cxx:65
 TBenchmark.cxx:66
 TBenchmark.cxx:67
 TBenchmark.cxx:68
 TBenchmark.cxx:69
 TBenchmark.cxx:70
 TBenchmark.cxx:71
 TBenchmark.cxx:72
 TBenchmark.cxx:73
 TBenchmark.cxx:74
 TBenchmark.cxx:75
 TBenchmark.cxx:76
 TBenchmark.cxx:77
 TBenchmark.cxx:78
 TBenchmark.cxx:79
 TBenchmark.cxx:80
 TBenchmark.cxx:81
 TBenchmark.cxx:82
 TBenchmark.cxx:83
 TBenchmark.cxx:84
 TBenchmark.cxx:85
 TBenchmark.cxx:86
 TBenchmark.cxx:87
 TBenchmark.cxx:88
 TBenchmark.cxx:89
 TBenchmark.cxx:90
 TBenchmark.cxx:91
 TBenchmark.cxx:92
 TBenchmark.cxx:93
 TBenchmark.cxx:94
 TBenchmark.cxx:95
 TBenchmark.cxx:96
 TBenchmark.cxx:97
 TBenchmark.cxx:98
 TBenchmark.cxx:99
 TBenchmark.cxx:100
 TBenchmark.cxx:101
 TBenchmark.cxx:102
 TBenchmark.cxx:103
 TBenchmark.cxx:104
 TBenchmark.cxx:105
 TBenchmark.cxx:106
 TBenchmark.cxx:107
 TBenchmark.cxx:108
 TBenchmark.cxx:109
 TBenchmark.cxx:110
 TBenchmark.cxx:111
 TBenchmark.cxx:112
 TBenchmark.cxx:113
 TBenchmark.cxx:114
 TBenchmark.cxx:115
 TBenchmark.cxx:116
 TBenchmark.cxx:117
 TBenchmark.cxx:118
 TBenchmark.cxx:119
 TBenchmark.cxx:120
 TBenchmark.cxx:121
 TBenchmark.cxx:122
 TBenchmark.cxx:123
 TBenchmark.cxx:124
 TBenchmark.cxx:125
 TBenchmark.cxx:126
 TBenchmark.cxx:127
 TBenchmark.cxx:128
 TBenchmark.cxx:129
 TBenchmark.cxx:130
 TBenchmark.cxx:131
 TBenchmark.cxx:132
 TBenchmark.cxx:133
 TBenchmark.cxx:134
 TBenchmark.cxx:135
 TBenchmark.cxx:136
 TBenchmark.cxx:137
 TBenchmark.cxx:138
 TBenchmark.cxx:139
 TBenchmark.cxx:140
 TBenchmark.cxx:141
 TBenchmark.cxx:142
 TBenchmark.cxx:143
 TBenchmark.cxx:144
 TBenchmark.cxx:145
 TBenchmark.cxx:146
 TBenchmark.cxx:147
 TBenchmark.cxx:148
 TBenchmark.cxx:149
 TBenchmark.cxx:150
 TBenchmark.cxx:151
 TBenchmark.cxx:152
 TBenchmark.cxx:153
 TBenchmark.cxx:154
 TBenchmark.cxx:155
 TBenchmark.cxx:156
 TBenchmark.cxx:157
 TBenchmark.cxx:158
 TBenchmark.cxx:159
 TBenchmark.cxx:160
 TBenchmark.cxx:161
 TBenchmark.cxx:162
 TBenchmark.cxx:163
 TBenchmark.cxx:164
 TBenchmark.cxx:165
 TBenchmark.cxx:166
 TBenchmark.cxx:167
 TBenchmark.cxx:168
 TBenchmark.cxx:169
 TBenchmark.cxx:170
 TBenchmark.cxx:171
 TBenchmark.cxx:172
 TBenchmark.cxx:173
 TBenchmark.cxx:174
 TBenchmark.cxx:175
 TBenchmark.cxx:176
 TBenchmark.cxx:177
 TBenchmark.cxx:178
 TBenchmark.cxx:179
 TBenchmark.cxx:180
 TBenchmark.cxx:181
 TBenchmark.cxx:182
 TBenchmark.cxx:183
 TBenchmark.cxx:184
 TBenchmark.cxx:185
 TBenchmark.cxx:186
 TBenchmark.cxx:187
 TBenchmark.cxx:188
 TBenchmark.cxx:189
 TBenchmark.cxx:190
 TBenchmark.cxx:191
 TBenchmark.cxx:192
 TBenchmark.cxx:193
 TBenchmark.cxx:194
 TBenchmark.cxx:195
 TBenchmark.cxx:196
 TBenchmark.cxx:197
 TBenchmark.cxx:198
 TBenchmark.cxx:199
 TBenchmark.cxx:200
 TBenchmark.cxx:201
 TBenchmark.cxx:202
 TBenchmark.cxx:203
 TBenchmark.cxx:204
 TBenchmark.cxx:205
 TBenchmark.cxx:206
 TBenchmark.cxx:207
 TBenchmark.cxx:208
 TBenchmark.cxx:209
 TBenchmark.cxx:210
 TBenchmark.cxx:211
 TBenchmark.cxx:212
 TBenchmark.cxx:213
 TBenchmark.cxx:214
 TBenchmark.cxx:215
 TBenchmark.cxx:216
 TBenchmark.cxx:217
 TBenchmark.cxx:218
 TBenchmark.cxx:219
 TBenchmark.cxx:220
 TBenchmark.cxx:221
 TBenchmark.cxx:222
 TBenchmark.cxx:223
 TBenchmark.cxx:224
 TBenchmark.cxx:225
 TBenchmark.cxx:226
 TBenchmark.cxx:227
 TBenchmark.cxx:228