00001
00002
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
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 int nobjects = 100;
00038 int ntimes = 100000;
00039 int moda = 0;
00040
00041
00042
00043 class HitNames {
00044 Int_t fSize;
00045 char** fNames;
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() {
00060
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() {
00068 if(!fNames) return;
00069
00070 for (int i=0;i<fSize;i++) {
00071 delete fNames[i];
00072 }
00073 delete fNames;
00074 fNames = 0;
00075 }
00076
00077 HitNames names;
00078
00079
00080
00081
00082
00083
00084
00085 class Tester : public TObject {
00086 enum EClass { Clones, Array, BTree, Other };
00087 EClass fWhat;
00088 Int_t fNobj;
00089 Int_t fNtimes;
00090 Int_t fModa;
00091 TCollection *fColl;
00092 public:
00093
00094 void Fill();
00095 Double_t TestAllocation();
00096 Double_t TestByName();
00097 Double_t TestByIndex();
00098 Double_t DoTest();
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() {
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() {
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() {
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
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;
00205 Double_t deltas[ntests];
00206
00207 int main(int argc,char **argv)
00208 {
00209
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
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);
00256
00257 array.Add(new Tester(nobjects,ntimes,moda,
00258 new 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)));
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()));
00271 j++;
00272 deltas[j] = ((Tester*)(array[j]))->DoTest();
00273 if(deltas[j] < smin) { idx=j; smin=deltas[j]; }
00274
00275 if(moda != 1) {
00276
00277 array.Add(new Tester(nobjects,ntimes,moda,
00278 new 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()));
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()));
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()));
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()));
00303 j++;
00304 deltas[j] = ((Tester*)(array[j]))->DoTest();
00305 if(deltas[j] < smin) { idx=j; smin=deltas[j]; }
00306 }
00307
00308
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 }