Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TTreePerfStats.cxx
Go to the documentation of this file.
1 // @(#)root/treeplayer:$Id$
2 // Author: Rene Brun 29/10/09
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TTreePerfStats
13 
14 TTree I/O performance measurement. see example of use below.
15 
16 The function FileReadEvent is called from TFile::ReadBuffer.
17 For each call the following information is stored in fGraphIO
18  - x[i] = Tree entry number
19  - y[i] = 1e-6*(file position)
20  - ey[i] = 1e-9*number of bytes read
21 For each call the following information is stored in fGraphTime
22  - x[i] = Tree entry number
23  - y[i] = Time now
24  - ey[i] = readtime, eg timenow - start
25 The TTreePerfStats object can be saved in a ROOT file in such a way that
26 its inspection can be done outside the job that generated it.
27 
28 Example of use:
29 ~~~{.cpp}
30 {
31  TFile *f = TFile::Open("RelValMinBias-GEN-SIM-RECO.root");
32  T = (TTree*)f->Get("Events");
33  Long64_t nentries = T->GetEntries();
34  T->SetCacheSize(10000000);
35  T->SetCacheEntryRange(0,nentries);
36  T->AddBranchToCache("*");
37 //
38  TTreePerfStats *ps= new TTreePerfStats("ioperf",T);
39 //
40  for (Int_t i=0;i<nentries;i++) {
41  T->GetEntry(i);
42  }
43  ps->SaveAs("cmsperf.root");
44 }
45 ~~~
46 then, in a root interactive session, one can do:
47 ~~~{.cpp}
48  root > TFile f("cmsperf.root");
49  root > ioperf->Draw();
50  root > ioperf->Print();
51 ~~~
52 The Draw or Print functions print the following information:
53  - TreeCache = TTree cache size in MBytes
54  - N leaves = Number of leaves in the TTree
55  - ReadTotal = Total number of zipped bytes read
56  - ReadUnZip = Total number of unzipped bytes read
57  - ReadCalls = Total number of disk reads
58  - ReadSize = Average read size in KBytes
59  - Readahead = Readahead size in KBytes
60  - Readextra = Readahead overhead in percent
61  - Real Time = Real Time in seconds
62  - CPU Time = CPU Time in seconds
63  - Disk Time = Real Time spent in pure raw disk IO
64  - Disk IO = Raw disk IO speed in MBytes/second
65  - ReadUZRT = Unzipped MBytes per RT second
66  - ReadUZCP = Unipped MBytes per CP second
67  - ReadRT = Zipped MBytes per RT second
68  - ReadCP = Zipped MBytes per CP second
69 
70  ### NOTE 1 :
71 The ReadTotal value indicates the effective number of zipped bytes
72 returned to the application. The physical number of bytes read
73 from the device (as measured for example with strace) is
74 ReadTotal +ReadTotal*Readextra/100. Same for ReadSize.
75 
76  ### NOTE 2 :
77 A consequence of NOTE1, the Disk I/O speed corresponds to the effective
78 number of bytes returned to the application per second.
79 The Physical disk speed is DiskIO + DiskIO*ReadExtra/100.
80 */
81 
82 #include "TTreePerfStats.h"
83 #include "TROOT.h"
84 #include "TSystem.h"
85 #include "Riostream.h"
86 #include "TFile.h"
87 #include "TTree.h"
88 #include "TTreeCache.h"
89 #include "TAxis.h"
90 #include "TBrowser.h"
91 #include "TVirtualPad.h"
92 #include "TPaveText.h"
93 #include "TGraphErrors.h"
94 #include "TStopwatch.h"
95 #include "TGaxis.h"
96 #include "TTimeStamp.h"
97 #include "TDatime.h"
98 #include "TMath.h"
99 
100 ClassImp(TTreePerfStats);
101 
102 ////////////////////////////////////////////////////////////////////////////////
103 /// default constructor (used when reading an object only)
104 
105 TTreePerfStats::TTreePerfStats() : TVirtualPerfStats()
106 {
107  fName = "";
108  fHostInfo = "";
109  fTree = 0;
110  fNleaves = 0;
111  fFile = 0;
112  fGraphIO = 0;
113  fGraphTime = 0;
114  fWatch = 0;
115  fPave = 0;
116  fTreeCacheSize = 0;
117  fReadCalls = 0;
118  fReadaheadSize = 0;
119  fBytesRead = 0;
120  fBytesReadExtra= 0;
121  fRealNorm = 0;
122  fRealTime = 0;
123  fCpuTime = 0;
124  fDiskTime = 0;
125  fUnzipTime = 0;
126  fCompress = 0;
127  fRealTimeAxis = 0;
128  fHostInfoText = 0;
129 }
130 
131 ////////////////////////////////////////////////////////////////////////////////
132 /// Create a TTree I/O perf stats object.
133 
134 TTreePerfStats::TTreePerfStats(const char *name, TTree *T) : TVirtualPerfStats()
135 {
136  fName = name;
137  fTree = T;
138  T->SetPerfStats(this);
139  fNleaves= T->GetListOfLeaves()->GetEntries();
140  fFile = T->GetCurrentFile();
141  fGraphIO = new TGraphErrors(0);
142  fGraphIO->SetName("ioperf");
143  fGraphIO->SetTitle(Form("%s/%s",fFile->GetName(),T->GetName()));
144  fGraphIO->SetUniqueID(999999999);
145  fGraphTime = new TGraphErrors(0);
146  fGraphTime->SetLineColor(kRed);
147  fGraphTime->SetName("iotime");
148  fGraphTime->SetTitle("Real time vs entries");
149  fWatch = new TStopwatch();
150  fWatch->Start();
151  fPave = 0;
152  fTreeCacheSize = 0;
153  fReadCalls = 0;
154  fReadaheadSize = 0;
155  fBytesRead = 0;
156  fBytesReadExtra= 0;
157  fRealNorm = 0;
158  fRealTime = 0;
159  fCpuTime = 0;
160  fDiskTime = 0;
161  fUnzipTime = 0;
162  fRealTimeAxis = 0;
163  fCompress = (T->GetTotBytes()+0.00001)/T->GetZipBytes();
164 
165  Bool_t isUNIX = strcmp(gSystem->GetName(), "Unix") == 0;
166  if (isUNIX)
167  fHostInfo = gSystem->GetFromPipe("uname -a");
168  else
169  fHostInfo = "Windows ";
170  fHostInfo.Resize(20);
171  fHostInfo += TString::Format("ROOT %s, Git: %s", gROOT->GetVersion(), gROOT->GetGitCommit());
172  TDatime dt;
173  fHostInfo += TString::Format(" %s",dt.AsString());
174  fHostInfoText = 0;
175 
176  gPerfStats = this;
177 }
178 
179 ////////////////////////////////////////////////////////////////////////////////
180 /// Destructor
181 
182 TTreePerfStats::~TTreePerfStats()
183 {
184  fTree = 0;
185  fFile = 0;
186  delete fGraphIO;
187  delete fGraphTime;
188  delete fPave;
189  delete fWatch;
190  delete fRealTimeAxis;
191  delete fHostInfoText;
192 
193  if (gPerfStats == this) {
194  gPerfStats = 0;
195  }
196 }
197 
198 
199 ////////////////////////////////////////////////////////////////////////////////
200 /// Browse
201 
202 void TTreePerfStats::Browse(TBrowser * /*b*/)
203 {
204  Draw();
205  gPad->Update();
206 }
207 
208 ////////////////////////////////////////////////////////////////////////////////
209 /// Return distance to one of the objects in the TTreePerfStats
210 
211 Int_t TTreePerfStats::DistancetoPrimitive(Int_t px, Int_t py)
212 {
213  const Int_t kMaxDiff = 7;
214  Int_t puxmin = gPad->XtoAbsPixel(gPad->GetUxmin());
215  Int_t puymin = gPad->YtoAbsPixel(gPad->GetUymin());
216  Int_t puxmax = gPad->XtoAbsPixel(gPad->GetUxmax());
217  Int_t puymax = gPad->YtoAbsPixel(gPad->GetUymax());
218  if (py < puymax) return 9999;
219  //on the fGraphIO ?
220  Int_t distance = fGraphIO->DistancetoPrimitive(px,py);
221  if (distance <kMaxDiff) {if (px > puxmin && py < puymin) gPad->SetSelected(fGraphIO); return distance;}
222  // on the fGraphTime ?
223  distance = fGraphTime->DistancetoPrimitive(px,py);
224  if (distance <kMaxDiff) {if (px > puxmin && py < puymin) gPad->SetSelected(fGraphTime); return distance;}
225  // on the pave ?
226  distance = fPave->DistancetoPrimitive(px,py);
227  if (distance <kMaxDiff) {gPad->SetSelected(fPave); return distance;}
228  // on the real time axis ?
229  distance = fRealTimeAxis->DistancetoPrimitive(px,py);
230  if (distance <kMaxDiff) {gPad->SetSelected(fRealTimeAxis); return distance;}
231  // on the host info label ?
232  distance = fHostInfoText->DistancetoPrimitive(px,py);
233  if (distance <kMaxDiff) {gPad->SetSelected(fHostInfoText); return distance;}
234  if (px > puxmax-300) return 2;
235  return 999;
236 }
237 
238 ////////////////////////////////////////////////////////////////////////////////
239 /// Draw the TTree I/O perf graph.
240 /// by default the graph is drawn with option "al"
241 /// Specify option ="ap" to show only the read blocks and not the line
242 /// connecting the blocks
243 
244 void TTreePerfStats::Draw(Option_t *option)
245 {
246  Finish();
247 
248  TString opt = option;
249  if (strlen(option)==0) opt = "al";
250  opt.ToLower();
251  if (gPad) {
252  if (!gPad->IsEditable()) gROOT->MakeDefCanvas();
253  //the following statement is necessary in case one attempts to draw
254  //a temporary histogram already in the current pad
255  if (TestBit(kCanDelete)) gPad->GetListOfPrimitives()->Remove(this);
256  } else {
257  gROOT->MakeDefCanvas();
258  }
259  if (opt.Contains("a")) {
260  gPad->SetLeftMargin(0.35);
261  gPad->Clear();
262  gPad->SetGridx();
263  gPad->SetGridy();
264  }
265  AppendPad(opt.Data());
266 }
267 
268 ////////////////////////////////////////////////////////////////////////////////
269 /// Return distance to one of the objects in the TTreePerfStats
270 
271 void TTreePerfStats::ExecuteEvent(Int_t /*event*/, Int_t /*px*/, Int_t /*py*/)
272 {
273 }
274 
275 ////////////////////////////////////////////////////////////////////////////////
276 /// Record TTree file read event.
277 /// - start is the TimeStamp before reading
278 /// - len is the number of bytes read
279 
280 void TTreePerfStats::FileReadEvent(TFile *file, Int_t len, Double_t start)
281 {
282  if (file == this->fFile){
283  Long64_t offset = file->GetRelOffset();
284  Int_t np = fGraphIO->GetN();
285  Int_t entry = fTree->GetReadEntry();
286  fGraphIO->SetPoint(np,entry,1e-6*offset);
287  fGraphIO->SetPointError(np,0.001,1e-9*len);
288  Double_t tnow = TTimeStamp();
289  Double_t dtime = tnow-start;
290  fDiskTime += dtime;
291  fGraphTime->SetPoint(np,entry,tnow);
292  fGraphTime->SetPointError(np,0.001,dtime);
293  fReadCalls++;
294  fBytesRead += len;
295  }
296 }
297 
298 
299 ////////////////////////////////////////////////////////////////////////////////
300 /// Record TTree unzip event.
301 /// - start is the TimeStamp before unzip
302 /// - pos is where in the file the compressed buffer came from
303 /// - complen is the length of the compressed buffer
304 /// - objlen is the length of the de-compressed buffer
305 
306 void TTreePerfStats::UnzipEvent(TObject * tree, Long64_t /* pos */, Double_t start, Int_t /* complen */, Int_t /* objlen */)
307 {
308  if (tree == this->fTree){
309  Double_t tnow = TTimeStamp();
310  Double_t dtime = tnow-start;
311  fUnzipTime += dtime;
312  }
313 }
314 
315 ////////////////////////////////////////////////////////////////////////////////
316 /// When the run is finished this function must be called
317 /// to save the current parameters in the file and Tree in this object
318 /// the function is automatically called by Draw and Print
319 
320 void TTreePerfStats::Finish()
321 {
322  if (fRealNorm) return; //has already been called
323  if (!fFile) return;
324  if (!fTree) return;
325  fTreeCacheSize = fTree->GetCacheSize();
326  fReadaheadSize = TFile::GetReadaheadSize();
327  fBytesReadExtra= fFile->GetBytesReadExtra();
328  fRealTime = fWatch->RealTime();
329  fCpuTime = fWatch->CpuTime();
330  Int_t npoints = fGraphIO->GetN();
331  if (!npoints) return;
332  Double_t iomax = TMath::MaxElement(npoints,fGraphIO->GetY());
333  fRealNorm = iomax/fRealTime;
334  fGraphTime->GetY()[0] = fRealNorm*fGraphTime->GetEY()[0];
335  // we normalize the fGraphTime such that it can be drawn on top of fGraphIO
336  for (Int_t i=1;i<npoints;i++) {
337  fGraphTime->GetY()[i] = fGraphTime->GetY()[i-1] +fRealNorm*fGraphTime->GetEY()[i];
338  fGraphTime->GetEY()[i] = 0;
339  }
340 }
341 
342 ////////////////////////////////////////////////////////////////////////////////
343 /// Update the fBranchIndexCache collection to match the current TTree given
344 /// the ordered list of branch names.
345 
346 void TTreePerfStats::UpdateBranchIndices(TObjArray *branches)
347 {
348  fBranchIndexCache.clear();
349 
350  for (int i = 0; i < branches->GetEntries(); ++i) {
351  fBranchIndexCache.emplace((TBranch*)(branches->UncheckedAt(i)), i);
352  }
353 }
354 
355 ////////////////////////////////////////////////////////////////////////////////
356 /// Return the BasketInfo corresponding to the given branch and basket.
357 
358 TTreePerfStats::BasketInfo &TTreePerfStats::GetBasketInfo(TBranch *br, size_t basketNumber)
359 {
360  static BasketInfo fallback;
361 
362  // First find the branch index.
363  TFile *file = fTree->GetCurrentFile();
364  if (!file)
365  return fallback;
366 
367  TTreeCache *cache = dynamic_cast<TTreeCache *>(file->GetCacheRead(fTree));
368  if (!cache)
369  return fallback;
370 
371  Int_t index = -1;
372  auto iter = fBranchIndexCache.find(br);
373  if (iter == fBranchIndexCache.end()) {
374  auto branches = cache->GetCachedBranches();
375  for (Int_t i = 0; i < branches->GetEntries(); ++i) {
376  if (br == branches->UncheckedAt(i)) {
377  index = i;
378  break;
379  }
380  }
381  if (index < 0)
382  return fallback;
383  fBranchIndexCache.emplace(br, index);
384  } else {
385  index = iter->second;
386  }
387 
388  return GetBasketInfo(index, basketNumber);
389 }
390 
391 ////////////////////////////////////////////////////////////////////////////////
392 /// Return the BasketInfo corresponding to the given branch and basket.
393 
394 TTreePerfStats::BasketInfo &TTreePerfStats::GetBasketInfo(size_t index, size_t basketNumber)
395 {
396  if (fBasketsInfo.size() <= (size_t)index)
397  fBasketsInfo.resize(index + 1);
398 
399  auto &brvec(fBasketsInfo[index]);
400  if (brvec.size() <= basketNumber)
401  brvec.resize(basketNumber + 1);
402 
403  return brvec[basketNumber];
404 }
405 
406 ////////////////////////////////////////////////////////////////////////////////
407 /// Return the collection of baskets which have been read by the TTreeCache more
408 /// than once
409 
410 TTreePerfStats::BasketList_t TTreePerfStats::GetDuplicateBasketCache() const
411 {
412  BasketList_t result;
413 
414  TFile *file = fTree->GetCurrentFile();
415  if (!file)
416  return result;
417 
418  TTreeCache *cache = dynamic_cast<TTreeCache *>(file->GetCacheRead(fTree));
419  if (!cache)
420  return result;
421 
422  auto branches = cache->GetCachedBranches();
423  for (size_t i = 0; i < fBasketsInfo.size(); ++i) {
424  Bool_t first = kTRUE;
425  for (size_t j = 0; j < fBasketsInfo[i].size(); ++j) {
426  auto &info(fBasketsInfo[i][j]);
427  if ((info.fLoaded + info.fLoadedMiss) > 1) {
428  if (first) {
429  result.emplace_back(BasketList_t::value_type((TBranch*)branches->At(i), std::vector<size_t>(1)));;
430  first = false;
431  }
432  auto &ref( result.back() );
433  ref.second.push_back(j);
434  }
435  }
436  }
437 
438  return result;
439 }
440 
441 ////////////////////////////////////////////////////////////////////////////////
442 /// Draw the TTree I/O perf graph.
443 
444 void TTreePerfStats::Paint(Option_t *option)
445 {
446  Int_t npoints = fGraphIO->GetN();
447  if (!npoints) return;
448  Double_t iomax = fGraphIO->GetY()[npoints-1];
449  Double_t toffset=1;
450  if (iomax >= 1e9) toffset = 1.2;
451  fGraphIO->GetXaxis()->SetTitle("Tree entry number");
452  fGraphIO->GetYaxis()->SetTitle("file position (MBytes) ");
453  fGraphIO->GetYaxis()->SetTitleOffset(toffset);
454  fGraphIO->GetXaxis()->SetLabelSize(0.03);
455  fGraphIO->GetYaxis()->SetLabelSize(0.03);
456  fGraphIO->Paint(option);
457 
458  TString opts(option);
459  opts.ToLower();
460  Bool_t unzip = opts.Contains("unzip");
461 
462  //superimpose the time info (max 10 points)
463  if (fGraphTime) {
464  fGraphTime->Paint("l");
465  TText tdisk(fGraphTime->GetX()[npoints-1],1.1*fGraphTime->GetY()[npoints-1],"RAW IO");
466  tdisk.SetTextAlign(31);
467  tdisk.SetTextSize(0.03);
468  tdisk.SetTextColor(kRed);
469  tdisk.Paint();
470  if (!fRealTimeAxis) {
471  Double_t uxmax = gPad->GetUxmax();
472  Double_t uymax = gPad->GetUymax();
473  Double_t rtmax = uymax/fRealNorm;
474  fRealTimeAxis = new TGaxis(uxmax,0,uxmax,uymax,0.,rtmax,510,"+L");
475  fRealTimeAxis->SetName("RealTimeAxis");
476  fRealTimeAxis->SetLineColor(kRed);
477  fRealTimeAxis->SetTitle("RealTime (s) ");
478  fRealTimeAxis->SetTitleColor(kRed);
479  toffset = 1;
480  if (fRealTime >= 100) toffset = 1.2;
481  if (fRealTime >= 1000) toffset = 1.4;
482  fRealTimeAxis->SetTitleOffset(toffset);
483  fRealTimeAxis->SetLabelSize(0.03);
484  fRealTimeAxis->SetLabelColor(kRed);
485  }
486  fRealTimeAxis->Paint();
487  }
488 
489  Double_t extra = 100.*fBytesReadExtra/fBytesRead;
490  if (!fPave) {
491  fPave = new TPaveText(.01,.10,.24,.90,"brNDC");
492  fPave->SetTextAlign(12);
493  fPave->AddText(Form("TreeCache = %d MB",fTreeCacheSize/1000000));
494  fPave->AddText(Form("N leaves = %d",fNleaves));
495  fPave->AddText(Form("ReadTotal = %g MB",1e-6*fBytesRead));
496  fPave->AddText(Form("ReadUnZip = %g MB",1e-6*fBytesRead*fCompress));
497  fPave->AddText(Form("ReadCalls = %d",fReadCalls));
498  fPave->AddText(Form("ReadSize = %7.3f KB",0.001*fBytesRead/fReadCalls));
499  fPave->AddText(Form("Readahead = %d KB",fReadaheadSize/1000));
500  fPave->AddText(Form("Readextra = %5.2f per cent",extra));
501  fPave->AddText(Form("Real Time = %7.3f s",fRealTime));
502  fPave->AddText(Form("CPU Time = %7.3f s",fCpuTime));
503  fPave->AddText(Form("Disk Time = %7.3f s",fDiskTime));
504  if (unzip) {
505  fPave->AddText(Form("UnzipTime = %7.3f s",fUnzipTime));
506  }
507  fPave->AddText(Form("Disk IO = %7.3f MB/s",1e-6*fBytesRead/fDiskTime));
508  fPave->AddText(Form("ReadUZRT = %7.3f MB/s",1e-6*fCompress*fBytesRead/fRealTime));
509  fPave->AddText(Form("ReadUZCP = %7.3f MB/s",1e-6*fCompress*fBytesRead/fCpuTime));
510  fPave->AddText(Form("ReadRT = %7.3f MB/s",1e-6*fBytesRead/fRealTime));
511  fPave->AddText(Form("ReadCP = %7.3f MB/s",1e-6*fBytesRead/fCpuTime));
512  }
513  fPave->Paint();
514 
515  if (!fHostInfoText) {
516  fHostInfoText = new TText(0.01,0.01,fHostInfo.Data());
517  fHostInfoText->SetNDC();
518  fHostInfoText->SetTextSize(0.025);
519  }
520  fHostInfoText->Paint();
521 }
522 
523 ////////////////////////////////////////////////////////////////////////////////
524 /// Print the TTree I/O perf stats.
525 
526 void TTreePerfStats::Print(Option_t * option) const
527 {
528  TString opts(option);
529  opts.ToLower();
530  Bool_t unzip = opts.Contains("unzip");
531  Bool_t basket = opts.Contains("basket");
532  TTreePerfStats *ps = (TTreePerfStats*)this;
533  ps->Finish();
534 
535  Double_t extra = 100.*fBytesReadExtra/fBytesRead;
536  printf("TreeCache = %d MBytes\n",Int_t(fTreeCacheSize/1000000));
537  printf("N leaves = %d\n",fNleaves);
538  printf("ReadTotal = %g MBytes\n",1e-6*fBytesRead);
539  printf("ReadUnZip = %g MBytes\n",1e-6*fBytesRead*fCompress);
540  printf("ReadCalls = %d\n",fReadCalls);
541  printf("ReadSize = %7.3f KBytes/read\n",0.001*fBytesRead/fReadCalls);
542  printf("Readahead = %d KBytes\n",fReadaheadSize/1000);
543  printf("Readextra = %5.2f per cent\n",extra);
544  printf("Real Time = %7.3f seconds\n",fRealTime);
545  printf("CPU Time = %7.3f seconds\n",fCpuTime);
546  printf("Disk Time = %7.3f seconds\n",fDiskTime);
547  if (unzip) {
548  printf("Strm Time = %7.3f seconds\n",fCpuTime-fUnzipTime);
549  printf("UnzipTime = %7.3f seconds\n",fUnzipTime);
550  }
551  printf("Disk IO = %7.3f MBytes/s\n",1e-6*fBytesRead/fDiskTime);
552  printf("ReadUZRT = %7.3f MBytes/s\n",1e-6*fCompress*fBytesRead/fRealTime);
553  printf("ReadUZCP = %7.3f MBytes/s\n",1e-6*fCompress*fBytesRead/fCpuTime);
554  printf("ReadRT = %7.3f MBytes/s\n",1e-6*fBytesRead/fRealTime);
555  printf("ReadCP = %7.3f MBytes/s\n",1e-6*fBytesRead/fCpuTime);
556  if (unzip) {
557  printf("ReadStrCP = %7.3f MBytes/s\n",1e-6*fCompress*fBytesRead/(fCpuTime-fUnzipTime));
558  printf("ReadZipCP = %7.3f MBytes/s\n",1e-6*fCompress*fBytesRead/fUnzipTime);
559  }
560  if (basket)
561  PrintBasketInfo(option);
562 }
563 
564 ////////////////////////////////////////////////////////////////////////////////
565 /// Print the TTree basket information
566 
567 void TTreePerfStats::PrintBasketInfo(Option_t *option) const
568 {
569 
570  TString opts(option);
571  opts.ToLower();
572  Bool_t all = opts.Contains("allbasketinfo");
573 
574  TFile *file = fTree->GetCurrentFile();
575  if (!file)
576  return;
577 
578  TTreeCache *cache = dynamic_cast<TTreeCache *>(file->GetCacheRead(fTree));
579  if (!cache)
580  return;
581 
582  auto branches = cache->GetCachedBranches();
583  for (size_t i = 0; i < fBasketsInfo.size(); ++i) {
584  const char *branchname = branches->At(i)->GetName();
585 
586  printf(" br=%zu %s read not cached: ", i, branchname);
587  if (fBasketsInfo[i].size() == 0) {
588  printf("none");
589  } else
590  for (size_t j = 0; j < fBasketsInfo[i].size(); ++j) {
591  if (fBasketsInfo[i][j].fMissed)
592  printf("%zu ", j);
593  }
594  printf("\n");
595 
596  printf(" br=%zu %s cached more than once: ", i, branchname);
597  for (size_t j = 0; j < fBasketsInfo[i].size(); ++j) {
598  auto &info(fBasketsInfo[i][j]);
599  if ((info.fLoaded + info.fLoadedMiss) > 1)
600  printf("%zu[%d,%d] ", j, info.fLoaded, info.fLoadedMiss);
601  }
602  printf("\n");
603 
604  printf(" br=%zu %s cached but not used: ", i, branchname);
605  for (size_t j = 0; j < fBasketsInfo[i].size(); ++j) {
606  auto &info(fBasketsInfo[i][j]);
607  if ((info.fLoaded + info.fLoadedMiss) && !info.fUsed) {
608  if (info.fLoadedMiss)
609  printf("%zu[%d,%d] ", j, info.fLoaded, info.fLoadedMiss);
610  else
611  printf("%zu ", j);
612  }
613  }
614  printf("\n");
615 
616  if (all) {
617  printf(" br=%zu %s: ", i, branchname);
618  for (size_t j = 0; j < fBasketsInfo[i].size(); ++j) {
619  auto &info(fBasketsInfo[i][j]);
620  printf("%zu[%d,%d,%d,%d] ", j, info.fUsed, info.fLoaded, info.fLoadedMiss, info.fMissed);
621  }
622  printf("\n");
623  }
624  }
625  for (Int_t i = fBasketsInfo.size(); i < branches->GetEntries(); ++i) {
626  printf(" br=%d %s: no basket information\n", i, branches->At(i)->GetName());
627  }
628 }
629 
630 ////////////////////////////////////////////////////////////////////////////////
631 /// Save this object to filename
632 
633 void TTreePerfStats::SaveAs(const char *filename, Option_t * /*option*/) const
634 {
635  TTreePerfStats *ps = (TTreePerfStats*)this;
636  ps->Finish();
637  ps->TObject::SaveAs(filename);
638 }
639 
640 ////////////////////////////////////////////////////////////////////////////////
641 /// Save primitive as a C++ statement(s) on output stream out
642 
643 void TTreePerfStats::SavePrimitive(std::ostream &out, Option_t *option /*= ""*/)
644 {
645  char quote = '"';
646  out<<" "<<std::endl;
647  if (gROOT->ClassSaved(TTreePerfStats::Class())) {
648  out<<" ";
649  } else {
650  out<<" TTreePerfStats *";
651  }
652  out<<"ps = new TTreePerfStats();"<<std::endl;
653  out<<" ps->SetName("<<quote<<GetName()<<quote<<");"<<std::endl;
654  out<<" ps->SetHostInfo("<<quote<<GetHostInfo()<<quote<<");"<<std::endl;
655  out<<" ps->SetTreeCacheSize("<<fTreeCacheSize<<");"<<std::endl;
656  out<<" ps->SetNleaves("<<fNleaves<<");"<<std::endl;
657  out<<" ps->SetReadCalls("<<fReadCalls<<");"<<std::endl;
658  out<<" ps->SetReadaheadSize("<<fReadaheadSize<<");"<<std::endl;
659  out<<" ps->SetBytesRead("<<fBytesRead<<");"<<std::endl;
660  out<<" ps->SetBytesReadExtra("<<fBytesReadExtra<<");"<<std::endl;
661  out<<" ps->SetRealNorm("<<fRealNorm<<");"<<std::endl;
662  out<<" ps->SetRealTime("<<fRealTime<<");"<<std::endl;
663  out<<" ps->SetCpuTime("<<fCpuTime<<");"<<std::endl;
664  out<<" ps->SetDiskTime("<<fDiskTime<<");"<<std::endl;
665  out<<" ps->SetUnzipTime("<<fUnzipTime<<");"<<std::endl;
666  out<<" ps->SetCompress("<<fCompress<<");"<<std::endl;
667 
668  Int_t i, npoints = fGraphIO->GetN();
669  out<<" TGraphErrors *psGraphIO = new TGraphErrors("<<npoints<<");"<<std::endl;
670  out<<" psGraphIO->SetName("<<quote<<fGraphIO->GetName()<<quote<<");"<<std::endl;
671  out<<" psGraphIO->SetTitle("<<quote<<fGraphIO->GetTitle()<<quote<<");"<<std::endl;
672  out<<" ps->SetGraphIO(psGraphIO);"<<std::endl;
673  fGraphIO->SaveFillAttributes(out,"psGraphIO",0,1001);
674  fGraphIO->SaveLineAttributes(out,"psGraphIO",1,1,1);
675  fGraphIO->SaveMarkerAttributes(out,"psGraphIO",1,1,1);
676  for (i=0;i<npoints;i++) {
677  out<<" psGraphIO->SetPoint("<<i<<","<<fGraphIO->GetX()[i]<<","<<fGraphIO->GetY()[i]<<");"<<std::endl;
678  out<<" psGraphIO->SetPointError("<<i<<",0,"<<fGraphIO->GetEY()[i]<<");"<<std::endl;
679  }
680  npoints = fGraphTime->GetN();
681  out<<" TGraphErrors *psGraphTime = new TGraphErrors("<<npoints<<");"<<std::endl;
682  out<<" psGraphTime->SetName("<<quote<<fGraphTime->GetName()<<quote<<");"<<std::endl;
683  out<<" psGraphTime->SetTitle("<<quote<<fGraphTime->GetTitle()<<quote<<");"<<std::endl;
684  out<<" ps->SetGraphTime(psGraphTime);"<<std::endl;
685  fGraphTime->SaveFillAttributes(out,"psGraphTime",0,1001);
686  fGraphTime->SaveLineAttributes(out,"psGraphTime",1,1,1);
687  fGraphTime->SaveMarkerAttributes(out,"psGraphTime",1,1,1);
688  for (i=0;i<npoints;i++) {
689  out<<" psGraphTime->SetPoint("<<i<<","<<fGraphTime->GetX()[i]<<","<<fGraphTime->GetY()[i]<<");"<<std::endl;
690  out<<" psGraphTime->SetPointError("<<i<<",0,"<<fGraphTime->GetEY()[i]<<");"<<std::endl;
691  }
692 
693  out<<" ps->Draw("<<quote<<option<<quote<<");"<<std::endl;
694 }