tcollbm.cxx

Go to the documentation of this file.
00001 // @(#)root/test:$Id: tcollbm.cxx 36320 2010-10-12 19:00:12Z brun $
00002 // Author: Nikolay Root   05/07/98
00003 
00004 #include <stdlib.h>
00005 
00006 #include "Riostream.h"
00007 #include "TCollection.h"
00008 #include "TSortedList.h"
00009 #include "TObjArray.h"
00010 #include "TClonesArray.h"
00011 #include "TOrdCollection.h"
00012 #include "THashList.h"
00013 #include "THashTable.h"
00014 #include "TBtree.h"
00015 
00016 #include "TStopwatch.h"
00017 #include "TRandom.h"
00018 //
00019 // This program benchmarks access time to objects by name or index
00020 // for TObjArray,TOrdCollection,TList,TSortedList,THashList,TBtree,
00021 // TClonesArray and THashTable collections.
00022 //
00023 // Usage: tcollbm -h                               - to print a usage info
00024 //        tcollbm [-n|-i|-m] [nobjects] [ntimes]   - to run tests
00025 //
00026 // switches:
00027 //       -n            - benchmark access by name  (default)
00028 //       -i            - benchmark access by index
00029 //       -m            - benchmark of objects allocation
00030 //
00031 // parameters:
00032 //       nobjects      - number of objects to be inserted into collections
00033 //       ntimes        - number of random lookups in the collection
00034 //
00035 //  default values  ( adjusted in 'main' according 'moda' value )
00036 
00037 int nobjects = 100;       // Number of objects to be inserted.
00038 int ntimes   = 100000;    // Number of random lookups.
00039 int moda     = 0;         // Default - access by name
00040 
00041 //_____________________________________________________________
00042 
00043 class HitNames {          // Utility class to handle the table of names
00044   Int_t  fSize;           // Array size
00045   char** fNames;          // Array for objects names
00046 public:
00047   void InitNames();
00048   void DeleteNames();
00049   void Resize(Int_t s) {
00050     if(s <= fSize) return;
00051     DeleteNames(); fSize=s; InitNames();
00052   }
00053   HitNames() : fSize(0), fNames(0) {};
00054   HitNames(Int_t s) : fSize(s), fNames(0) { InitNames(); };
00055   virtual ~HitNames()                     { DeleteNames(); };
00056   const char *operator[](Int_t i)       { return fNames[i]; };
00057 };
00058 
00059 void HitNames::InitNames() {        // Create and fill names
00060   //  cout << "HitNames::InitNames() are called" << endl;
00061   fNames = new char* [fSize];
00062   for (int i=0;i<fSize;i++) {
00063     fNames[i] = new char [20];
00064     sprintf(fNames[i],"W%d",i+1);
00065   }
00066 }
00067 void HitNames::DeleteNames() {      // Clean up
00068   if(!fNames) return;
00069   //  cout << "HitNames::DeleteNames() are called" << endl;
00070   for (int i=0;i<fSize;i++) {
00071     delete fNames[i];
00072   }
00073   delete fNames;
00074   fNames = 0;
00075 }
00076 
00077 HitNames names;   // We needs only one static object of this class
00078 
00079 //_______________________________________________________________
00080 //
00081 // Just for fun, I introduce the class 'Tester' to collect
00082 // a 'TNamed' objects. I use a objects of this class to perform a real
00083 // tests.
00084 
00085 class Tester : public TObject {
00086   enum EClass { Clones, Array, BTree, Other };
00087   EClass        fWhat;
00088   Int_t         fNobj;       // Number of objects to be stored in collection
00089   Int_t         fNtimes;     // How many times to perform a test
00090   Int_t         fModa;       // What we need to test
00091   TCollection  *fColl;       // Collection under test
00092 public:
00093 
00094   void Fill();               // Fill the collection
00095   Double_t TestAllocation(); // Memory allocation test
00096   Double_t TestByName();     // benchmark by name
00097   Double_t TestByIndex();    // benchmark by index
00098   Double_t DoTest();         // Tests multiplexsor
00099 
00100   void        CleanUp()    { fColl->Delete(); }
00101   void        Dump() const { fColl->Dump(); }
00102 
00103   virtual const char* GetName() const
00104   { return fColl->ClassName(); }
00105 
00106   Tester() :
00107     fWhat(Other),fNobj(10),fNtimes(100000),fModa(0),fColl(0) {}
00108   Tester(Int_t no,Int_t nt,Int_t m,TCollection *p) :
00109     fWhat(Other),fNobj(no),fNtimes(nt),fModa(m),fColl(p) {
00110       if(!strcmp(GetName(),"TClonesArray")) fWhat = Clones;
00111       if(!strcmp(GetName(),"TObjArray"))    fWhat = Array;
00112       if(!strcmp(GetName(),"TBtree"))       fWhat = BTree;
00113   }
00114   virtual ~Tester() { if(fColl) delete fColl; }
00115 };
00116 
00117 void Tester::Fill() {
00118   if (fWhat == Clones) {
00119     TClonesArray &base = *((TClonesArray*)fColl);
00120     for (Int_t i=0;i<fNobj;i++) new (base[i]) TNamed(names[i],GetName());
00121   } else {
00122     for (Int_t i=0;i<fNobj;i++) fColl->Add(new TNamed(names[i],GetName()));
00123   }
00124 }
00125 
00126 Double_t Tester::TestAllocation() {   // benchmark memory allocation
00127   TStopwatch timer;
00128   timer.Start();
00129   for (Int_t i=0;i<fNtimes;i++) {
00130     Fill();
00131     CleanUp();
00132   }
00133   timer.Stop();
00134   return timer.CpuTime();
00135 }
00136 
00137 Double_t Tester::TestByIndex() {      // benchmark access by index
00138   Fill();
00139   TStopwatch timer;
00140   Int_t i;
00141   if (fWhat == Clones) {
00142     TClonesArray *o = (TClonesArray*)fColl;
00143     timer.Start();
00144     for (Int_t j=0;j<fNtimes;j++) {
00145       i=Int_t(fNobj*gRandom->Rndm(1));
00146       if(!((*o)[i])) Printf("Object %d not found !!!",i);
00147     }
00148     timer.Stop();
00149   } else if(fWhat == Array) {
00150     TObjArray    *o = (TObjArray*)fColl;
00151     timer.Start();
00152     for (Int_t j=0;j<fNtimes;j++) {
00153       i=Int_t(fNobj*gRandom->Rndm(1));
00154       if(!((*o)[i])) Printf("Object %d not found !!!",i);
00155     }
00156     timer.Stop();
00157   } else if(fWhat == BTree) {
00158     TBtree       *o = (TBtree*)fColl;
00159     timer.Start();
00160     for (Int_t j=0;j<fNtimes;j++) {
00161       i=Int_t(fNobj*gRandom->Rndm(1));
00162       if(!((*o)[i])) Printf("Object %d not found !!!",i);
00163     }
00164     timer.Stop();
00165   } else {
00166     cout << "Class " << GetName()
00167          << " doesn't support access by index" << endl;
00168   }
00169   CleanUp();
00170   return timer.CpuTime();
00171 };
00172 
00173 Double_t Tester::TestByName() {           // benchmark access by name
00174   Fill();
00175   TStopwatch timer;
00176   Int_t i;
00177   timer.Start();
00178   for (Int_t j=0;j<fNtimes;j++) {
00179     i=Int_t(fNobj*gRandom->Rndm(1));
00180     if(!((*fColl)(names[i]))) Printf("Object %5s not found !!!",names[i]);
00181   }
00182   timer.Stop();
00183   CleanUp();
00184   return timer.CpuTime();
00185 };
00186 
00187 Double_t Tester::DoTest() {
00188   // Return the average time in msec.
00189   Double_t v;
00190   if(fModa==2) {
00191     printf("Memory allocation test for %-20s", GetName());
00192     v=TestAllocation();
00193   } else if(fModa==1) {
00194     printf("Random lookups by Index for %-20s", GetName());
00195     v=TestByIndex();
00196   } else {
00197     printf("Random lookups by Name for %-20s", GetName());
00198     v=TestByName();
00199   }
00200   Printf(" CpuTime=%7.2f seconds", v);
00201   return 1000*v/fNtimes;
00202 };
00203 //_______________________________________________________________
00204 const int ntests = 8;     // Number of classes to be tested
00205 Double_t deltas[ntests];  // benchmark results
00206 
00207 int main(int argc,char **argv)
00208 {
00209   // Initialize the ROOT framework
00210   if(argc == 2 && !strcmp(argv[1],"-h")) {
00211     Printf("Usage: tcollbm [-n|-i] [nobjects] [ntimes]");
00212     Printf("  -n        - benchmark access by name");
00213     Printf("  -i        - benchmark access by index");
00214     Printf("  -m        - benchmark memory allocation");
00215     Printf("  nobjects  - number of objects to be inserted into collections");
00216     Printf("  ntimes    - number of random lookups in the collection");
00217     return 1;
00218   }
00219   if(argc > 1 && !strcmp(argv[1],"-n")) { moda = 0; argc--; argv++; };
00220   if(argc > 1 && !strcmp(argv[1],"-i")) { moda = 1; argc--; argv++; };
00221   if(argc > 1 && !strcmp(argv[1],"-m")) { moda = 2; argc--; argv++; };
00222   //
00223   // Set defaults values for selected test
00224   //
00225   if(moda == 0) { nobjects = 100;  ntimes = 10000; }
00226   if(moda == 1) { nobjects = 100;  ntimes = 1000000; }
00227   if(moda == 2) { nobjects = 1000; ntimes = 100; }
00228 
00229   Int_t no = nobjects;
00230   Int_t nt = ntimes;
00231   if(argc > 1) { no = atoi(argv[1]); }
00232   if(argc > 2) { nt = atoi(argv[2]); }
00233   if(no > 1) {
00234     nobjects = no;
00235   } else {
00236     nobjects = 2;
00237     Printf("Reset nobjects to %d",nobjects);
00238   }
00239   if(nt > 99) {
00240     ntimes   = nt;
00241   } else {
00242     ntimes = 100;
00243     Printf("Reset ntimes   to %d",ntimes);
00244   }
00245 
00246   Printf("Nobjects = %d , Ntimes = %d",nobjects,ntimes);
00247 
00248   if(ntimes > 5000000 || (moda==2 && nobjects*ntimes > 500000)) {
00249     Printf("This test takes some time. Be partient ...");
00250   }
00251 
00252   names.Resize(nobjects);
00253   Double_t smin = 10000000;
00254   int j=-1,idx=-1;
00255   TObjArray array(ntests);                         // Array of collections
00256 
00257   array.Add(new Tester(nobjects,ntimes,moda,
00258                         new TObjArray()));         // Add TObjArray
00259   j++;
00260   deltas[j] = ((Tester*)(array[j]))->DoTest();
00261   if(deltas[j] < smin) { idx=j; smin=deltas[j]; }
00262 
00263   array.Add(new Tester(nobjects,ntimes,moda,
00264             new TClonesArray("TNamed",nobjects)));  // Add TClonesArray
00265   j++;
00266   deltas[j] = ((Tester*)(array[j]))->DoTest();
00267   if(deltas[j] < smin) { idx=j; smin=deltas[j]; }
00268 
00269   array.Add(new Tester(nobjects,ntimes,moda,
00270             new TBtree()));                       // Add TBTree
00271   j++;
00272   deltas[j] = ((Tester*)(array[j]))->DoTest();
00273   if(deltas[j] < smin) { idx=j; smin=deltas[j]; }
00274 
00275   if(moda != 1) {   // Skip classes without operator[] from index test
00276 
00277     array.Add(new Tester(nobjects,ntimes,moda,
00278               new TOrdCollection()));            // Add TOrdCollection
00279     j++;
00280     deltas[j] = ((Tester*)(array[j]))->DoTest();
00281     if(deltas[j] < smin) { idx=j; smin=deltas[j]; }
00282 
00283     array.Add(new Tester(nobjects,ntimes,moda,
00284               new TList()));                     // Add TList
00285     j++;
00286     deltas[j] = ((Tester*)(array[j]))->DoTest();
00287     if(deltas[j] < smin) { idx=j; smin=deltas[j]; }
00288 
00289     array.Add(new Tester(nobjects,ntimes,moda,
00290               new TSortedList()));               // Add TSortedList
00291     j++;
00292     deltas[j] = ((Tester*)(array[j]))->DoTest();
00293     if(deltas[j] < smin) { idx=j; smin=deltas[j]; }
00294 
00295     array.Add(new Tester(nobjects,ntimes,moda,
00296               new THashList()));                 // Add THashList
00297     j++;
00298     deltas[j] = ((Tester*)(array[j]))->DoTest();
00299     if(deltas[j] < smin) { idx=j; smin=deltas[j]; }
00300 
00301     array.Add(new Tester(nobjects,ntimes,moda,
00302               new THashTable()));                // Add THashTable
00303     j++;
00304     deltas[j] = ((Tester*)(array[j]))->DoTest();
00305     if(deltas[j] < smin) { idx=j; smin=deltas[j]; }
00306   }
00307 
00308   //          Results info ...
00309   j++;
00310   if(idx<0) {
00311     Printf("Can not find the winner. Sorry...\n");
00312     array.Delete();
00313     return 1;
00314   }
00315   if(smin==0) {
00316     Printf(
00317     "Input parameters nobjects=%d and ntimes=%d too small for Your computer.",
00318     nobjects,ntimes);
00319     Printf("Please, increase its and try again...");
00320     array.Delete();
00321     return 1;
00322   }
00323 
00324   Printf("\n\t\tBenchmark results\n");
00325   Printf("\tAbsolute winner - %s",array[idx]->GetName());
00326 
00327   Printf("\tAverage (msec)\tRatio\t\tClassName");
00328 
00329   for (int i=0;i<j;i++) {
00330     Printf("\t%f\t%f\t%s",
00331            deltas[i],deltas[i]/smin,array[i]->GetName());
00332   }
00333   array.Delete();
00334   return 0;
00335 }

Generated on Tue Jul 5 15:16:14 2011 for ROOT_528-00b_version by  doxygen 1.5.1