TTreePerfStats.cxx

Go to the documentation of this file.
00001 // @(#)root/treeplayer:$Id: TTreePerfStats.cxx 36345 2010-10-13 20:54:09Z brun $
00002 // Author: Rene Brun 29/10/09
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      
00014 //                       TTreePerfStats                                                       
00015 //                                                                      
00016 //        TTree I/O performance measurement. see example of use below.
00017 //
00018 // The function FileReadEvent is called from TFile::ReadBuffer.
00019 // For each call the following information is stored in fGraphIO
00020 //     - x[i]  = Tree entry number
00021 //     - y[i]  = 1e-6*(file position)
00022 //     - ey[i] = 1e-9*number of bytes read
00023 // For each call the following information is stored in fGraphTime
00024 //     - x[i]  = Tree entry number
00025 //     - y[i]  = Time now
00026 //     - ey[i] = readtime, eg timenow - start
00027 // The TTreePerfStats object can be saved in a ROOT file in such a way that
00028 // its inspection can be done outside the job that generated it.
00029 //
00030 //       Example of use                                                 
00031 // {
00032 //   TFile *f = TFile::Open("RelValMinBias-GEN-SIM-RECO.root");
00033 //   T = (TTree*)f->Get("Events");
00034 //   Long64_t nentries = T->GetEntries();
00035 //   T->SetCacheSize(10000000);
00036 //   T->SetCacheEntryRange(0,nentries);
00037 //   T->AddBranchToCache("*");
00038 //
00039 //   TTreePerfStats *ps= new TTreePerfStats("ioperf",T);
00040 //
00041 //   for (Int_t i=0;i<nentries;i++) {
00042 //      T->GetEntry(i);
00043 //   }
00044 //   ps->SaveAs("cmsperf.root");
00045 // }
00046 //
00047 // then, in a root interactive session, one can do:
00048 //    root > TFile f("cmsperf.root");
00049 //    root > ioperf->Draw();
00050 //    root > ioperf->Print();
00051 //
00052 // The Draw or Print functions print the following information:
00053 //   TreeCache = TTree cache size in MBytes
00054 //   N leaves  = Number of leaves in the TTree
00055 //   ReadTotal = Total number of zipped bytes read
00056 //   ReadUnZip = Total number of unzipped bytes read
00057 //   ReadCalls = Total number of disk reads
00058 //   ReadSize  = Average read size in KBytes
00059 //   Readahead = Readahead size in KBytes
00060 //   Readextra = Readahead overhead in percent
00061 //   Real Time = Real Time in seconds
00062 //   CPU  Time = CPU Time in seconds
00063 //   Disk Time = Real Time spent in pure raw disk IO
00064 //   Disk IO   = Raw disk IO speed in MBytes/second
00065 //   ReadUZRT  = Unzipped MBytes per RT second
00066 //   ReadUZCP  = Unipped MBytes per CP second
00067 //   ReadRT    = Zipped MBytes per RT second
00068 //   ReadCP    = Zipped MBytes per CP second
00069 //
00070 //   NOTE1 : The ReadTotal value indicates the effective number of zipped bytes
00071 //           returned to the application. The physical number of bytes read
00072 //           from the device (as measured for example with strace) is
00073 //           ReadTotal +ReadTotal*Readextra/100. Same for ReadSize.
00074 //
00075 //   NOTE2 : A consequence of NOTE1, the Disk I/O speed corresponds to the effective
00076 //           number of bytes returned to the application per second.
00077 //           The Physical disk speed is DiskIO + DiskIO*ReadExtra/100.
00078 //
00079 //////////////////////////////////////////////////////////////////////////
00080 
00081 
00082 #include "TTreePerfStats.h"
00083 #include "TROOT.h"
00084 #include "TSystem.h"
00085 #include "Riostream.h"
00086 #include "TFile.h"
00087 #include "TTree.h"
00088 #include "TAxis.h"
00089 #include "TBrowser.h"
00090 #include "TVirtualPad.h"
00091 #include "TPaveText.h"
00092 #include "TGraphErrors.h"
00093 #include "TStopwatch.h"
00094 #include "TGaxis.h"
00095 #include "TTimeStamp.h"
00096 #include "TDatime.h"
00097 #include "TMath.h"
00098 
00099 const Double_t kScaleTime = 1e-20;
00100 
00101 ClassImp(TTreePerfStats)
00102 
00103 //______________________________________________________________________________
00104 TTreePerfStats::TTreePerfStats() : TVirtualPerfStats()
00105 {
00106    // default constructor (used when reading an object only)
00107 
00108    fName      = "";
00109    fHostInfo  = "";
00110    fTree      = 0;
00111    fNleaves   = 0;
00112    fFile      = 0;
00113    fGraphIO   = 0;
00114    fGraphTime = 0;
00115    fWatch     = 0;
00116    fPave      = 0;
00117    fTreeCacheSize = 0;
00118    fReadCalls     = 0;
00119    fReadaheadSize = 0;
00120    fBytesRead     = 0;
00121    fBytesReadExtra= 0;
00122    fRealNorm      = 0;
00123    fRealTime      = 0;
00124    fCpuTime       = 0;
00125    fDiskTime      = 0;
00126    fCompress      = 0;
00127    fRealTimeAxis  = 0;
00128    fHostInfoText  = 0;
00129 }
00130 
00131 //______________________________________________________________________________
00132 TTreePerfStats::TTreePerfStats(const char *name, TTree *T) : TVirtualPerfStats()
00133 {
00134    // Create a TTree I/O perf stats object.
00135 
00136    fName   = name;
00137    fTree   = T;
00138    fNleaves= T->GetListOfLeaves()->GetEntries();
00139    fFile   = T->GetCurrentFile();
00140    fGraphIO  = new TGraphErrors(0);
00141    fGraphIO->SetName("ioperf");
00142    fGraphIO->SetTitle(Form("%s/%s",fFile->GetName(),T->GetName()));
00143    fGraphIO->SetUniqueID(999999999);
00144    fGraphTime = new TGraphErrors(0);   
00145    fGraphTime->SetLineColor(kRed);
00146    fGraphTime->SetName("iotime");
00147    fGraphTime->SetTitle("Real time vs entries");
00148    fWatch  = new TStopwatch();
00149    fWatch->Start();
00150    fPave  = 0;
00151    fTreeCacheSize = 0;
00152    fReadCalls     = 0;
00153    fReadaheadSize = 0;
00154    fBytesRead     = 0;
00155    fBytesReadExtra= 0;
00156    fRealNorm      = 0;
00157    fRealTime      = 0;
00158    fCpuTime       = 0;
00159    fDiskTime      = 0;
00160    fRealTimeAxis  = 0;
00161    fCompress      = (T->GetTotBytes()+0.00001)/T->GetZipBytes();
00162    
00163    Bool_t isUNIX = strcmp(gSystem->GetName(), "Unix") == 0;
00164    if (isUNIX) fHostInfo = gSystem->GetFromPipe("uname -a");
00165    else      fHostInfo = "Windows ";
00166    fHostInfo.Resize(20);
00167    fHostInfo += Form("Root%s, SVN :%d",gROOT->GetVersion(),gROOT->GetSvnRevision());
00168    TDatime dt;
00169    fHostInfo += Form(" %s",dt.AsString());
00170    fHostInfoText   = 0;
00171 
00172    gPerfStats = this;
00173 }
00174 
00175 //______________________________________________________________________________
00176 TTreePerfStats::~TTreePerfStats()
00177 {
00178    // Destructor
00179    
00180    fTree = 0;
00181    fFile = 0;
00182    delete fGraphIO;
00183    delete fGraphTime;
00184    delete fPave;
00185    delete fWatch;
00186    delete fRealTimeAxis;
00187    delete fHostInfoText;
00188 
00189    if (gPerfStats == this) {
00190       gPerfStats = 0;
00191    }
00192 }
00193 
00194 
00195 //______________________________________________________________________________
00196 void TTreePerfStats::Browse(TBrowser * /*b*/)
00197 {
00198    // Browse
00199    
00200    Draw();
00201    gPad->Update();
00202 }
00203 
00204 //______________________________________________________________________________
00205 Int_t TTreePerfStats::DistancetoPrimitive(Int_t px, Int_t py)
00206 {
00207    // Return distance to one of the objects in the TTreePerfStats
00208    
00209    const Int_t kMaxDiff = 7;
00210    Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
00211    Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
00212    Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
00213    Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
00214    if (py < puymax) return 9999;
00215    //on the fGraphIO ?
00216    Int_t distance = fGraphIO->DistancetoPrimitive(px,py);
00217    if (distance <kMaxDiff) {if (px > puxmin && py < puymin) gPad->SetSelected(fGraphIO); return distance;}
00218    // on the fGraphTime ?
00219    distance = fGraphTime->DistancetoPrimitive(px,py);
00220    if (distance <kMaxDiff) {if (px > puxmin && py < puymin) gPad->SetSelected(fGraphTime); return distance;}
00221    // on the pave ?
00222    distance = fPave->DistancetoPrimitive(px,py);
00223    if (distance <kMaxDiff) {gPad->SetSelected(fPave);  return distance;}
00224    // on the real time axis ?
00225    distance = fRealTimeAxis->DistancetoPrimitive(px,py);
00226    if (distance <kMaxDiff) {gPad->SetSelected(fRealTimeAxis);  return distance;}
00227    // on the host info label ?
00228    distance = fHostInfoText->DistancetoPrimitive(px,py);
00229    if (distance <kMaxDiff) {gPad->SetSelected(fHostInfoText);  return distance;}
00230    if (px > puxmax-300) return 2;
00231    return 999;
00232 }
00233 
00234 //______________________________________________________________________________
00235 void TTreePerfStats::Draw(Option_t *option)
00236 {
00237    // Draw the TTree I/O perf graph.
00238    // by default the graph is drawn with option "al"
00239    // Specify option ="ap" to show only the read blocks and not the line
00240    // connecting the blocks
00241 
00242    Finish();
00243    
00244    TString opt = option;
00245    if (strlen(option)==0) opt = "al";
00246    opt.ToLower();
00247    if (gPad) {
00248       if (!gPad->IsEditable()) gROOT->MakeDefCanvas();
00249       //the following statement is necessary in case one attempts to draw
00250       //a temporary histogram already in the current pad
00251       if (TestBit(kCanDelete)) gPad->GetListOfPrimitives()->Remove(this);
00252    } else {
00253       gROOT->MakeDefCanvas();
00254    }
00255    if (opt.Contains("a")) {
00256       gPad->SetLeftMargin(0.35);
00257       gPad->Clear();
00258       gPad->SetGridx();
00259       gPad->SetGridy();
00260    }
00261    AppendPad(opt.Data());
00262 }
00263 
00264 //______________________________________________________________________________
00265 void TTreePerfStats::ExecuteEvent(Int_t /*event*/, Int_t /*px*/, Int_t /*py*/)
00266 {
00267    // Return distance to one of the objects in the TTreePerfStats
00268    
00269 }
00270 
00271 //______________________________________________________________________________
00272 void TTreePerfStats::FileReadEvent(TFile *file, Int_t len, Double_t start)
00273 {
00274    // Record TTree file read event.
00275    // start is the TimeStamp before reading
00276    // len is the number of bytes read
00277 
00278    Long64_t offset = file->GetRelOffset();
00279    Int_t np = fGraphIO->GetN();
00280    Int_t entry = fTree->GetReadEntry();
00281    fGraphIO->SetPoint(np,entry,1e-6*offset);
00282    fGraphIO->SetPointError(np,0.001,1e-9*len);
00283    Double_t tnow = TTimeStamp();
00284    Double_t dtime = tnow-start;
00285    fDiskTime += dtime;
00286    fGraphTime->SetPoint(np,entry,tnow);
00287    fGraphTime->SetPointError(np,0.001,dtime);
00288 }
00289 
00290 //______________________________________________________________________________
00291 void TTreePerfStats::Finish()
00292 {
00293    // When the run is finished this function must be called
00294    // to save the current parameters in the file and Tree in this object
00295    // the function is automatically called by Draw and Print
00296    
00297    if (fReadCalls)  return;  //has already been called
00298    if (!fFile)      return;
00299    if (!fTree)      return;
00300    fReadCalls     = fFile->GetReadCalls();
00301    fTreeCacheSize = fTree->GetCacheSize();
00302    fReadaheadSize = TFile::GetReadaheadSize();
00303    fBytesRead     = fFile->GetBytesRead();
00304    fBytesReadExtra= fFile->GetBytesReadExtra();
00305    fRealTime      = fWatch->RealTime();
00306    fCpuTime       = fWatch->CpuTime();
00307    Int_t npoints  = fGraphIO->GetN();
00308    if (!npoints) return;
00309    Double_t iomax = TMath::MaxElement(npoints,fGraphIO->GetY());
00310    fRealNorm      = iomax/fRealTime;
00311    fGraphTime->GetY()[0] = fRealNorm*fGraphTime->GetEY()[0];
00312    // we normalize the fGraphTime such that it can be drawn on top of fGraphIO
00313    for (Int_t i=1;i<npoints;i++) {
00314       fGraphTime->GetY()[i]   = fGraphTime->GetY()[i-1] +fRealNorm*fGraphTime->GetEY()[i];
00315       fGraphTime->GetEY()[i]  = 0;
00316    }
00317 }
00318    
00319 
00320 //______________________________________________________________________________
00321 void TTreePerfStats::Paint(Option_t *option)
00322 {
00323    // Draw the TTree I/O perf graph.
00324 
00325    Int_t npoints  = fGraphIO->GetN();
00326    if (!npoints) return;
00327    Double_t iomax = fGraphIO->GetY()[npoints-1];
00328    Double_t toffset=1;
00329    if (iomax >= 1e9) toffset = 1.2;
00330    fGraphIO->GetXaxis()->SetTitle("Tree entry number");
00331    fGraphIO->GetYaxis()->SetTitle("file position (MBytes)  ");
00332    fGraphIO->GetYaxis()->SetTitleOffset(toffset);
00333    fGraphIO->GetXaxis()->SetLabelSize(0.03);
00334    fGraphIO->GetYaxis()->SetLabelSize(0.03);
00335    fGraphIO->Paint(option);
00336    
00337    //superimpose the time info (max 10 points)
00338    if (fGraphTime) {
00339       fGraphTime->Paint("l");
00340       TText tdisk(fGraphTime->GetX()[npoints-1],1.1*fGraphTime->GetY()[npoints-1],"RAW IO");
00341       tdisk.SetTextAlign(31);
00342       tdisk.SetTextSize(0.03);
00343       tdisk.SetTextColor(kRed);
00344       tdisk.Paint();
00345       if (!fRealTimeAxis) {
00346          Double_t uxmax = gPad->GetUxmax();
00347          Double_t uymax = gPad->GetUymax();
00348          Double_t rtmax = uymax/fRealNorm;
00349          fRealTimeAxis = new TGaxis(uxmax,0,uxmax,uymax,0.,rtmax,510,"+L");
00350          fRealTimeAxis->SetName("RealTimeAxis");
00351          fRealTimeAxis->SetLineColor(kRed);
00352          fRealTimeAxis->SetTitle("RealTime (s)  ");
00353          fRealTimeAxis->SetTitleColor(kRed);
00354          toffset = 1;
00355          if (fRealTime >=  100) toffset = 1.2;
00356          if (fRealTime >= 1000) toffset = 1.4;
00357          fRealTimeAxis->SetTitleOffset(toffset);
00358          fRealTimeAxis->SetLabelSize(0.03);
00359          fRealTimeAxis->SetLabelColor(kRed);
00360       }
00361       fRealTimeAxis->Paint();
00362    }
00363 
00364    Double_t extra = 100.*fBytesReadExtra/fBytesRead;
00365    if (!fPave) {
00366       fPave = new TPaveText(.01,.10,.24,.90,"brNDC");
00367       fPave->SetTextAlign(12);
00368       fPave->AddText(Form("TreeCache = %d MB",fTreeCacheSize/1000000));
00369       fPave->AddText(Form("N leaves  = %d",fNleaves));
00370       fPave->AddText(Form("ReadTotal = %g MB",1e-6*fBytesRead));
00371       fPave->AddText(Form("ReadUnZip = %g MB",1e-6*fBytesRead*fCompress));
00372       fPave->AddText(Form("ReadCalls = %d",fReadCalls));
00373       fPave->AddText(Form("ReadSize  = %7.3f KB",0.001*fBytesRead/fReadCalls));
00374       fPave->AddText(Form("Readahead = %d KB",fReadaheadSize/1000));
00375       fPave->AddText(Form("Readextra = %5.2f per cent",extra));
00376       fPave->AddText(Form("Real Time = %7.3f s",fRealTime));
00377       fPave->AddText(Form("CPU  Time = %7.3f s",fCpuTime));
00378       fPave->AddText(Form("Disk Time = %7.3f s",fDiskTime));
00379       fPave->AddText(Form("Disk IO   = %7.3f MB/s",1e-6*fBytesRead/fDiskTime));
00380       fPave->AddText(Form("ReadUZRT  = %7.3f MB/s",1e-6*fCompress*fBytesRead/fRealTime));
00381       fPave->AddText(Form("ReadUZCP  = %7.3f MB/s",1e-6*fCompress*fBytesRead/fCpuTime));
00382       fPave->AddText(Form("ReadRT    = %7.3f MB/s",1e-6*fBytesRead/fRealTime));
00383       fPave->AddText(Form("ReadCP    = %7.3f MB/s",1e-6*fBytesRead/fCpuTime));
00384    }
00385    fPave->Paint();
00386    
00387    if (!fHostInfoText) {
00388       fHostInfoText = new TText(0.01,0.01,fHostInfo.Data());
00389       fHostInfoText->SetNDC();
00390       fHostInfoText->SetTextSize(0.025);
00391    }
00392    fHostInfoText->Paint();
00393 }
00394 
00395 //______________________________________________________________________________
00396 void TTreePerfStats::Print(Option_t * /*option*/) const
00397 {
00398    // Print the TTree I/O perf stats.
00399 
00400    TTreePerfStats *ps = (TTreePerfStats*)this;
00401    ps->Finish();
00402       
00403    Double_t extra = 100.*fBytesReadExtra/fBytesRead;
00404    printf("TreeCache = %d MBytes\n",Int_t(fTreeCacheSize/1000000));
00405    printf("N leaves  = %d\n",fNleaves);
00406    printf("ReadTotal = %g MBytes\n",1e-6*fBytesRead);
00407    printf("ReadUnZip = %g MBytes\n",1e-6*fBytesRead*fCompress);
00408    printf("ReadCalls = %d\n",fReadCalls);
00409    printf("ReadSize  = %7.3f KBytes/read\n",0.001*fBytesRead/fReadCalls);
00410    printf("Readahead = %d KBytes\n",fReadaheadSize/1000);
00411    printf("Readextra = %5.2f per cent\n",extra);
00412    printf("Real Time = %7.3f seconds\n",fRealTime);
00413    printf("CPU  Time = %7.3f seconds\n",fCpuTime);
00414    printf("Disk Time = %7.3f seconds\n",fDiskTime);
00415    printf("Disk IO   = %7.3f MBytes/s\n",1e-6*fBytesRead/fDiskTime);
00416    printf("ReadUZRT  = %7.3f MBytes/s\n",1e-6*fCompress*fBytesRead/fRealTime);
00417    printf("ReadUZCP  = %7.3f MBytes/s\n",1e-6*fCompress*fBytesRead/fCpuTime);
00418    printf("ReadRT    = %7.3f MBytes/s\n",1e-6*fBytesRead/fRealTime);
00419    printf("ReadCP    = %7.3f MBytes/s\n",1e-6*fBytesRead/fCpuTime);
00420 }
00421 
00422 //______________________________________________________________________________
00423 void TTreePerfStats::SaveAs(const char *filename, Option_t * /*option*/) const
00424 {
00425    // Save this object to filename
00426    
00427    TTreePerfStats *ps = (TTreePerfStats*)this;
00428    ps->Finish();
00429    ps->TObject::SaveAs(filename);
00430 }
00431 
00432 //______________________________________________________________________________
00433 void TTreePerfStats::SavePrimitive(ostream &out, Option_t *option /*= ""*/)
00434 {
00435     // Save primitive as a C++ statement(s) on output stream out
00436 
00437    char quote = '"';
00438    out<<"   "<<endl;
00439    if (gROOT->ClassSaved(TTreePerfStats::Class())) {
00440       out<<"   ";
00441    } else {
00442       out<<"   TTreePerfStats *";
00443    }
00444    out<<"ps = new TTreePerfStats();"<<endl;
00445    out<<"   ps->SetName("<<quote<<GetName()<<quote<<");"<<endl;
00446    out<<"   ps->SetHostInfo("<<quote<<GetHostInfo()<<quote<<");"<<endl;
00447    out<<"   ps->SetTreeCacheSize("<<fTreeCacheSize<<");"<<endl;
00448    out<<"   ps->SetNleaves("<<fNleaves<<");"<<endl;
00449    out<<"   ps->SetReadCalls("<<fReadCalls<<");"<<endl;
00450    out<<"   ps->SetReadaheadSize("<<fReadaheadSize<<");"<<endl;
00451    out<<"   ps->SetBytesRead("<<fBytesRead<<");"<<endl;
00452    out<<"   ps->SetBytesReadExtra("<<fBytesReadExtra<<");"<<endl;
00453    out<<"   ps->SetRealNorm("<<fRealNorm<<");"<<endl;
00454    out<<"   ps->SetRealTime("<<fRealTime<<");"<<endl;
00455    out<<"   ps->SetCpuTime("<<fCpuTime<<");"<<endl;
00456    out<<"   ps->SetDiskTime("<<fDiskTime<<");"<<endl;
00457    out<<"   ps->SetCompress("<<fCompress<<");"<<endl;
00458 
00459    Int_t i, npoints = fGraphIO->GetN();
00460    out<<"   TGraphErrors *psGraphIO = new TGraphErrors("<<npoints<<");"<<endl;
00461    out<<"   psGraphIO->SetName("<<quote<<fGraphIO->GetName()<<quote<<");"<<endl;
00462    out<<"   psGraphIO->SetTitle("<<quote<<fGraphIO->GetTitle()<<quote<<");"<<endl;
00463    out<<"   ps->SetGraphIO(psGraphIO);"<<endl;
00464    fGraphIO->SaveFillAttributes(out,"psGraphIO",0,1001);
00465    fGraphIO->SaveLineAttributes(out,"psGraphIO",1,1,1);
00466    fGraphIO->SaveMarkerAttributes(out,"psGraphIO",1,1,1);
00467    for (i=0;i<npoints;i++) {
00468       out<<"   psGraphIO->SetPoint("<<i<<","<<fGraphIO->GetX()[i]<<","<<fGraphIO->GetY()[i]<<");"<<endl;
00469       out<<"   psGraphIO->SetPointError("<<i<<",0,"<<fGraphIO->GetEY()[i]<<");"<<endl;
00470    }
00471    npoints = fGraphTime->GetN();
00472    out<<"   TGraphErrors *psGraphTime = new TGraphErrors("<<npoints<<");"<<endl;
00473    out<<"   psGraphTime->SetName("<<quote<<fGraphTime->GetName()<<quote<<");"<<endl;
00474    out<<"   psGraphTime->SetTitle("<<quote<<fGraphTime->GetTitle()<<quote<<");"<<endl;
00475    out<<"   ps->SetGraphTime(psGraphTime);"<<endl;
00476    fGraphTime->SaveFillAttributes(out,"psGraphTime",0,1001);
00477    fGraphTime->SaveLineAttributes(out,"psGraphTime",1,1,1);
00478    fGraphTime->SaveMarkerAttributes(out,"psGraphTime",1,1,1);
00479    for (i=0;i<npoints;i++) {
00480       out<<"   psGraphTime->SetPoint("<<i<<","<<fGraphTime->GetX()[i]<<","<<fGraphTime->GetY()[i]<<");"<<endl;
00481       out<<"   psGraphTime->SetPointError("<<i<<",0,"<<fGraphTime->GetEY()[i]<<");"<<endl;
00482    }
00483 
00484    out<<"   ps->Draw("<<quote<<option<<quote<<");"<<endl;
00485 }

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