100 ClassImp(TTreePerfStats);
105 TTreePerfStats::TTreePerfStats() : TVirtualPerfStats()
134 TTreePerfStats::TTreePerfStats(
const char *name, TTree *T) : TVirtualPerfStats()
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();
163 fCompress = (T->GetTotBytes()+0.00001)/T->GetZipBytes();
165 Bool_t isUNIX = strcmp(gSystem->GetName(),
"Unix") == 0;
167 fHostInfo = gSystem->GetFromPipe(
"uname -a");
169 fHostInfo =
"Windows ";
170 fHostInfo.Resize(20);
171 fHostInfo += TString::Format(
"ROOT %s, Git: %s", gROOT->GetVersion(), gROOT->GetGitCommit());
173 fHostInfo += TString::Format(
" %s",dt.AsString());
182 TTreePerfStats::~TTreePerfStats()
190 delete fRealTimeAxis;
191 delete fHostInfoText;
193 if (gPerfStats ==
this) {
202 void TTreePerfStats::Browse(TBrowser * )
211 Int_t TTreePerfStats::DistancetoPrimitive(Int_t px, Int_t py)
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;
220 Int_t distance = fGraphIO->DistancetoPrimitive(px,py);
221 if (distance <kMaxDiff) {
if (px > puxmin && py < puymin) gPad->SetSelected(fGraphIO);
return distance;}
223 distance = fGraphTime->DistancetoPrimitive(px,py);
224 if (distance <kMaxDiff) {
if (px > puxmin && py < puymin) gPad->SetSelected(fGraphTime);
return distance;}
226 distance = fPave->DistancetoPrimitive(px,py);
227 if (distance <kMaxDiff) {gPad->SetSelected(fPave);
return distance;}
229 distance = fRealTimeAxis->DistancetoPrimitive(px,py);
230 if (distance <kMaxDiff) {gPad->SetSelected(fRealTimeAxis);
return distance;}
232 distance = fHostInfoText->DistancetoPrimitive(px,py);
233 if (distance <kMaxDiff) {gPad->SetSelected(fHostInfoText);
return distance;}
234 if (px > puxmax-300)
return 2;
244 void TTreePerfStats::Draw(Option_t *option)
248 TString opt = option;
249 if (strlen(option)==0) opt =
"al";
252 if (!gPad->IsEditable()) gROOT->MakeDefCanvas();
255 if (TestBit(kCanDelete)) gPad->GetListOfPrimitives()->Remove(
this);
257 gROOT->MakeDefCanvas();
259 if (opt.Contains(
"a")) {
260 gPad->SetLeftMargin(0.35);
265 AppendPad(opt.Data());
271 void TTreePerfStats::ExecuteEvent(Int_t , Int_t , Int_t )
280 void TTreePerfStats::FileReadEvent(TFile *file, Int_t len, Double_t start)
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;
291 fGraphTime->SetPoint(np,entry,tnow);
292 fGraphTime->SetPointError(np,0.001,dtime);
306 void TTreePerfStats::UnzipEvent(TObject * tree, Long64_t , Double_t start, Int_t , Int_t )
308 if (tree == this->fTree){
309 Double_t tnow = TTimeStamp();
310 Double_t dtime = tnow-start;
320 void TTreePerfStats::Finish()
322 if (fRealNorm)
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];
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;
346 void TTreePerfStats::UpdateBranchIndices(TObjArray *branches)
348 fBranchIndexCache.clear();
350 for (
int i = 0; i < branches->GetEntries(); ++i) {
351 fBranchIndexCache.emplace((TBranch*)(branches->UncheckedAt(i)), i);
358 TTreePerfStats::BasketInfo &TTreePerfStats::GetBasketInfo(TBranch *br,
size_t basketNumber)
360 static BasketInfo fallback;
363 TFile *file = fTree->GetCurrentFile();
367 TTreeCache *cache =
dynamic_cast<TTreeCache *
>(file->GetCacheRead(fTree));
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)) {
383 fBranchIndexCache.emplace(br, index);
385 index = iter->second;
388 return GetBasketInfo(index, basketNumber);
394 TTreePerfStats::BasketInfo &TTreePerfStats::GetBasketInfo(
size_t index,
size_t basketNumber)
396 if (fBasketsInfo.size() <= (size_t)index)
397 fBasketsInfo.resize(index + 1);
399 auto &brvec(fBasketsInfo[index]);
400 if (brvec.size() <= basketNumber)
401 brvec.resize(basketNumber + 1);
403 return brvec[basketNumber];
410 TTreePerfStats::BasketList_t TTreePerfStats::GetDuplicateBasketCache()
const
414 TFile *file = fTree->GetCurrentFile();
418 TTreeCache *cache =
dynamic_cast<TTreeCache *
>(file->GetCacheRead(fTree));
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) {
429 result.emplace_back(BasketList_t::value_type((TBranch*)branches->At(i), std::vector<size_t>(1)));;
432 auto &ref( result.back() );
433 ref.second.push_back(j);
444 void TTreePerfStats::Paint(Option_t *option)
446 Int_t npoints = fGraphIO->GetN();
447 if (!npoints)
return;
448 Double_t iomax = fGraphIO->GetY()[npoints-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);
458 TString opts(option);
460 Bool_t unzip = opts.Contains(
"unzip");
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);
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);
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);
486 fRealTimeAxis->Paint();
489 Double_t extra = 100.*fBytesReadExtra/fBytesRead;
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));
505 fPave->AddText(Form(
"UnzipTime = %7.3f s",fUnzipTime));
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));
515 if (!fHostInfoText) {
516 fHostInfoText =
new TText(0.01,0.01,fHostInfo.Data());
517 fHostInfoText->SetNDC();
518 fHostInfoText->SetTextSize(0.025);
520 fHostInfoText->Paint();
526 void TTreePerfStats::Print(Option_t * option)
const
528 TString opts(option);
530 Bool_t unzip = opts.Contains(
"unzip");
531 Bool_t basket = opts.Contains(
"basket");
532 TTreePerfStats *ps = (TTreePerfStats*)
this;
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);
548 printf(
"Strm Time = %7.3f seconds\n",fCpuTime-fUnzipTime);
549 printf(
"UnzipTime = %7.3f seconds\n",fUnzipTime);
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);
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);
561 PrintBasketInfo(option);
567 void TTreePerfStats::PrintBasketInfo(Option_t *option)
const
570 TString opts(option);
572 Bool_t all = opts.Contains(
"allbasketinfo");
574 TFile *file = fTree->GetCurrentFile();
578 TTreeCache *cache =
dynamic_cast<TTreeCache *
>(file->GetCacheRead(fTree));
582 auto branches = cache->GetCachedBranches();
583 for (
size_t i = 0; i < fBasketsInfo.size(); ++i) {
584 const char *branchname = branches->At(i)->GetName();
586 printf(
" br=%zu %s read not cached: ", i, branchname);
587 if (fBasketsInfo[i].size() == 0) {
590 for (
size_t j = 0; j < fBasketsInfo[i].size(); ++j) {
591 if (fBasketsInfo[i][j].fMissed)
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);
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);
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);
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());
633 void TTreePerfStats::SaveAs(
const char *filename, Option_t * )
const
635 TTreePerfStats *ps = (TTreePerfStats*)
this;
637 ps->TObject::SaveAs(filename);
643 void TTreePerfStats::SavePrimitive(std::ostream &out, Option_t *option )
647 if (gROOT->ClassSaved(TTreePerfStats::Class())) {
650 out<<
" TTreePerfStats *";
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;
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;
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;
693 out<<
" ps->Draw("<<quote<<option<<quote<<
");"<<std::endl;