From 62991193793467cb586fa1c94238467cbbd3f123 Mon Sep 17 00:00:00 2001 From: Rene Brun <Rene.Brun@cern.ch> Date: Fri, 16 Jun 2006 11:01:17 +0000 Subject: [PATCH] Introduce two new major optimizations for the Tree cache. -in case of a TChain, the list of branches computed during the training phase of the first file is reused for all the other files. -add support for TEventlist. Only the baskets referenced by the list are added to the cache. This has requested a new function in TEventlist Bool_t TEventList::ContainsRange(Long64_t entrymin, Long64_t entrymax) // Return TRUE if list contains entries from entrymin to entrymax included. git-svn-id: http://root.cern.ch/svn/root/trunk@15455 27541ba8-7e3a-0410-8455-c3a389f83636 --- tree/inc/TEventList.h | 3 +- tree/inc/TTreeFilePrefetch.h | 15 +++-- tree/src/TChain.cxx | 8 +-- tree/src/TEventList.cxx | 14 +++- tree/src/TTree.cxx | 11 +-- tree/src/TTreeFilePrefetch.cxx | 119 +++++++++++++++++++++++---------- treeplayer/src/TTreePlayer.cxx | 3 +- 7 files changed, 115 insertions(+), 58 deletions(-) diff --git a/tree/inc/TEventList.h b/tree/inc/TEventList.h index b359a0e4a65..db9291efedc 100644 --- a/tree/inc/TEventList.h +++ b/tree/inc/TEventList.h @@ -1,4 +1,4 @@ -// @(#)root/tree:$Name: $:$Id: TEventList.h,v 1.10 2005/06/03 07:37:06 brun Exp $ +// @(#)root/tree:$Name: $:$Id: TEventList.h,v 1.11 2005/11/11 22:16:04 pcanal Exp $ // Author: Rene Brun 11/02/97 /************************************************************************* @@ -48,6 +48,7 @@ public: virtual void Add(const TEventList *list); virtual void Clear(Option_t *option="") {Reset(option);} virtual Bool_t Contains(Long64_t entry); + virtual Bool_t ContainsRange(Long64_t entrymin, Long64_t entrymax); virtual void Enter(Long64_t entry); TDirectory *GetDirectory() const {return fDirectory;} virtual Long64_t GetEntry(Int_t index) const; diff --git a/tree/inc/TTreeFilePrefetch.h b/tree/inc/TTreeFilePrefetch.h index 0a4117766fa..2f0c0e15f47 100644 --- a/tree/inc/TTreeFilePrefetch.h +++ b/tree/inc/TTreeFilePrefetch.h @@ -1,4 +1,4 @@ -// @(#)root/tree:$Name: $:$Id: TTreeFilePrefetch.h,v 1.5 2006/06/15 07:59:19 brun Exp $ +// @(#)root/tree:$Name: $:$Id: TTreeFilePrefetch.h,v 1.6 2006/06/15 10:02:13 brun Exp $ // Author: Rene Brun 04/06/2006 /************************************************************************* @@ -37,8 +37,11 @@ protected: Long64_t fZipBytes; //! Total compressed size of branches in cache Int_t fNbranches; //! Number of branches in the cache TBranch **fBranches; //! [fNbranches] List of branches to be stored in the cache + TList *fBrNames; //! list of branch names in the cache + TTree *fOwner; //! pointer to the owner Tree/chain + TTree *fTree; //! pointer to the current Tree Bool_t fIsLearning; //! true if cache is in learning mode - static Double_t fgLearnRatio; //fraction of entries used for learning mode + static Int_t fgLearnEntries; //Number of entries used for learning mode protected: TTreeFilePrefetch(const TTreeFilePrefetch &); //this class cannot be copied @@ -49,15 +52,15 @@ public: TTreeFilePrefetch(TTree *tree, Int_t buffersize=0); virtual ~TTreeFilePrefetch(); void AddBranch(TBranch *b); - void Clear(Option_t *option=""); - static Double_t GetLearnRatio(); + static Int_t GetLearnEntries(); Bool_t FillBuffer(); TTree *GetTree() const; Bool_t IsLearning() const {return fIsLearning;} virtual Bool_t ReadBuffer(char *buf, Long64_t pos, Int_t len); void SetEntryRange(Long64_t emin, Long64_t emax); - static void SetLearnRatio(Double_t ratio=0.01); - + static void SetLearnEntries(Int_t n = 100); + void UpdateBranches(TTree *tree); + ClassDef(TTreeFilePrefetch,1) //Specialization of TFilePrefetch for a TTree }; diff --git a/tree/src/TChain.cxx b/tree/src/TChain.cxx index 88535c84457..5ff64640040 100644 --- a/tree/src/TChain.cxx +++ b/tree/src/TChain.cxx @@ -1,4 +1,4 @@ -// @(#)root/tree:$Name: $:$Id: TChain.cxx,v 1.132 2006/06/08 16:59:02 pcanal Exp $ +// @(#)root/tree:$Name: $:$Id: TChain.cxx,v 1.133 2006/06/14 13:15:55 brun Exp $ // Author: Rene Brun 03/02/97 /************************************************************************* @@ -1006,10 +1006,9 @@ Long64_t TChain::LoadTree(Long64_t entry) if (tpf) { fFile->SetFilePrefetch(tpf); tpf->SetFile(fFile); - tpf->Clear(); - tpf->SetEntryRange(0,fTree->GetEntries()); + tpf->UpdateBranches(fTree); } else { - fTree->SetCacheSize(fCacheSize); + this->SetCacheSize(fCacheSize); } //check if fTreeOffset has really been set @@ -1389,6 +1388,7 @@ Long64_t TChain::Process(const char *filename,Option_t *option, Long64_t nentri { // Process all entries in this chain, calling functions in filename // see TTree::Process + if (fChainProof) return fChainProof->Process(filename, option, nentries, firstentry); diff --git a/tree/src/TEventList.cxx b/tree/src/TEventList.cxx index 0ab847bf1ce..2dc34131bfe 100644 --- a/tree/src/TEventList.cxx +++ b/tree/src/TEventList.cxx @@ -1,4 +1,4 @@ -// @(#)root/tree:$Name: $:$Id: TEventList.cxx,v 1.13 2005/06/03 07:37:06 brun Exp $ +// @(#)root/tree:$Name: $:$Id: TEventList.cxx,v 1.14 2005/11/11 22:16:04 pcanal Exp $ // Author: Rene Brun 11/02/97 /************************************************************************* @@ -162,6 +162,18 @@ Bool_t TEventList::Contains(Long64_t entry) return kTRUE; } +//______________________________________________________________________________ +Bool_t TEventList::ContainsRange(Long64_t entrymin, Long64_t entrymax) +{ + // Return TRUE if list contains entries from entrymin to entrymax included. + + Long64_t imax = TMath::BinarySearch(fN,fList,entrymax); + //printf("ContainsRange: entrymin=%lld, entrymax=%lld,imax=%lld, fList[imax]=%lld\n",entrymin,entrymax,imax,fList[imax]); + + if (fList[imax] < entrymin) return kFALSE; + return kTRUE; +} + //______________________________________________________________________________ void TEventList::Enter(Long64_t entry) { diff --git a/tree/src/TTree.cxx b/tree/src/TTree.cxx index 78e834dd38f..e8972e8dec7 100644 --- a/tree/src/TTree.cxx +++ b/tree/src/TTree.cxx @@ -1,4 +1,4 @@ -// @(#)root/tree:$Name: $:$Id: TTree.cxx,v 1.286 2006/06/08 13:26:01 brun Exp $ +// @(#)root/tree:$Name: $:$Id: TTree.cxx,v 1.287 2006/06/13 06:53:20 brun Exp $ // Author: Rene Brun 12/01/96 /************************************************************************* @@ -38,13 +38,8 @@ */ //End_Html // -// ==> TTree *tree = new TTree(name, title, maxvirtualsize) -// Creates a Tree with name and title. Maxvirtualsize is by default 64Mbytes, -// maxvirtualsize = 64000000(default) means: Keeps as many buffers in memory until -// the sum of all buffers is greater than 64 Megabyte. When this happens, -// memory buffers are written to disk and deleted until the size of all -// buffers is again below the threshold. -// maxvirtualsize = 0 means: keep only one buffer in memory. +// ==> TTree *tree = new TTree(name, title) +// Creates a Tree with name and title. // // Various kinds of branches can be added to a tree: // A - simple structures or list of variables. (may be for C or Fortran structures) diff --git a/tree/src/TTreeFilePrefetch.cxx b/tree/src/TTreeFilePrefetch.cxx index 675612128e3..b7d39e19bfc 100644 --- a/tree/src/TTreeFilePrefetch.cxx +++ b/tree/src/TTreeFilePrefetch.cxx @@ -1,4 +1,4 @@ -// @(#)root/tree:$Name: $:$Id: TTreeFilePrefetch.cxx,v 1.9 2006/06/15 07:59:19 brun Exp $ +// @(#)root/tree:$Name: $:$Id: TTreeFilePrefetch.cxx,v 1.10 2006/06/15 10:02:13 brun Exp $ // Author: Rene Brun 04/06/2006 /************************************************************************* @@ -17,8 +17,8 @@ // This class acts as a file cache, registering automatically the // // baskets from the branches being processed (TTree::Draw or // // TTree::Process and TSelectors) when in the learning phase. // -// The learning phase is by default the first 1 per cent of entries. // -// It can be changed via TTreeFileFrefetch::SetLearnRatio. // +// The learning phase is by default 100 entries. // +// It can be changed via TTreeFileFrefetch::SetLearnEntries. // // // // This cache speeds-up considerably the performance, in particular // // when the Tree is accessed remotely via a high latency network. // @@ -30,15 +30,25 @@ // // // For each Tree being processed a TTreeFilePrefetch object is created.// // This object is automatically deleted when the Tree is deleted or // -// when the file is deleted. +// when the file is deleted. // +// // +// -Special case of a TChain // +// Once the training is done on the first Tree, the list of branches // +// in the cache is kept for the following files. // +// // +// -Special case of a TEventlist // +// if the Tree or TChain has a TEventlist, only the buffers // +// referenced by the list are put in the cache. // // // ////////////////////////////////////////////////////////////////////////// #include "TTreeFilePrefetch.h" -#include "TTree.h" +#include "TChain.h" #include "TBranch.h" +#include "TEventList.h" +#include "TObjString.h" -Double_t TTreeFilePrefetch::fgLearnRatio = 0.01; +Int_t TTreeFilePrefetch::fgLearnEntries = 100; ClassImp(TTreeFilePrefetch) @@ -50,6 +60,9 @@ TTreeFilePrefetch::TTreeFilePrefetch() : TFilePrefetch(), fZipBytes(0), fNbranches(0), fBranches(0), + fBrNames(0), + fOwner(0), + fTree(0), fIsLearning(kTRUE) { // Default Constructor. @@ -63,13 +76,16 @@ TTreeFilePrefetch::TTreeFilePrefetch(TTree *tree, Int_t buffersize) : TFilePrefe fZipBytes(0), fNbranches(0), fBranches(0), + fBrNames(new TList), + fOwner(tree), + fTree(0), fIsLearning(kTRUE) { // Constructor. - fEntryNext = Long64_t(fgLearnRatio*(fEntryMax-fEntryMin)); - if (fEntryNext == fEntryMin) fEntryNext++; + + fEntryNext = fEntryMin + fgLearnEntries; Int_t nleaves = tree->GetListOfLeaves()->GetEntries(); - fBranches = new TBranch*[nleaves]; + fBranches = new TBranch*[nleaves+10]; //add a margin just in case in a TChain? } //______________________________________________________________________________ @@ -84,6 +100,7 @@ TTreeFilePrefetch::~TTreeFilePrefetch() // destructor. (in general called by the TFile destructor delete [] fBranches; + if (fBrNames) {fBrNames->Delete(); delete fBrNames;} } //______________________________________________________________________________ @@ -109,25 +126,15 @@ void TTreeFilePrefetch::AddBranch(TBranch *b) if (fBranches[i] == b) {isNew = kFALSE; break;} } if (isNew) { + fTree = b->GetTree(); fBranches[fNbranches] = b; - fNbranches++; + fBrNames->Add(new TObjString(b->GetName())); fZipBytes += b->GetZipBytes(); + fNbranches++; if (gDebug > 0) printf("Entry: %lld, registering branch: %s\n",b->GetTree()->GetReadEntry(),b->GetName()); } } -//_____________________________________________________________________________ -void TTreeFilePrefetch::Clear(Option_t *) -{ - //clear the cache (called by TChain::LoadTree) - - Prefetch(0,0); - fNbranches = 0; - fZipBytes = 0; - fIsLearning = kTRUE; -} - - //_____________________________________________________________________________ Bool_t TTreeFilePrefetch::FillBuffer() { @@ -141,7 +148,20 @@ Bool_t TTreeFilePrefetch::FillBuffer() //estimate number of entries that can fit in the cache fEntryNext = entry + tree->GetEntries()*fBufferSize/fZipBytes; if (fEntryNext > fEntryMax) fEntryNext = fEntryMax+1; - + + //check if owner has a TEventList set. If yes we optimize for this special case + //reading only the baskets containing entries in the list + TEventList *elist = fOwner->GetEventList(); + Long64_t chainOffset = 0; + if (elist) { + fEntryNext = fTree->GetEntries(); + if (fOwner->IsA() ==TChain::Class()) { + TChain *chain = (TChain*)fOwner; + Int_t t = chain->GetTreeNumber(); + chainOffset = chain->GetTreeOffset()[t]; + } + } + //clear cache buffer TFilePrefetch::Prefetch(0,0); //store baskets @@ -159,6 +179,11 @@ Bool_t TTreeFilePrefetch::FillBuffer() if (pos <= 0 || len <= 0) continue; if (entries[j] > fEntryNext) continue; if (entries[j] < entry && (j<nb-1 && entries[j+1] < entry)) continue; + if (elist) { + Long64_t emax = fEntryMax; + if (j<nb-1) emax = entries[j+1]-1; + if (!elist->ContainsRange(entries[j]+chainOffset,emax+chainOffset)) continue; + } TFilePrefetch::Prefetch(pos,len); } if (gDebug > 0) printf("Entry: %lld, registering baskets branch %s, fEntryNext=%lld, fNseek=%d, fNtot=%d\n",entry,fBranches[i]->GetName(),fEntryNext,fNseek,fNtot); @@ -169,12 +194,12 @@ Bool_t TTreeFilePrefetch::FillBuffer() //_____________________________________________________________________________ -Double_t TTreeFilePrefetch::GetLearnRatio() +Int_t TTreeFilePrefetch::GetLearnEntries() { - //static function returning fgLearnRatio - //see SetLearnRatio + //static function returning the number of entries used to train the cache + //see SetLearnEntries - return fgLearnRatio; + return fgLearnEntries; } //_____________________________________________________________________________ @@ -214,23 +239,45 @@ void TTreeFilePrefetch::SetEntryRange(Long64_t emin, Long64_t emax) fEntryMin = emin; fEntryMax = emax; - Long64_t learn = Long64_t(fgLearnRatio*(fEntryMax-fEntryMin)); - if (learn < 2) learn = 2; - fEntryNext = emin + learn; + fEntryNext = fEntryMin + fgLearnEntries; fIsLearning = kTRUE; fNbranches = 0; fZipBytes = 0; + if (fBrNames) fBrNames->Delete(); if (gDebug > 0) printf("SetEntryRange: fEntryMin=%lld, fEntryMax=%lld, fEntryNext=%lld\n",fEntryMin,fEntryMax,fEntryNext); } //_____________________________________________________________________________ -void TTreeFilePrefetch::SetLearnRatio(Double_t ratio) +void TTreeFilePrefetch::SetLearnEntries(Int_t n) +{ + // Static function to set the number of entries to be used in learning mode + // The default value for n is 10. n must be >= 1 + + if (n < 1) n = 1; + fgLearnEntries = n; +} + +//_____________________________________________________________________________ +void TTreeFilePrefetch::UpdateBranches(TTree *tree) { - // Static function to set the fraction of entries to be used in learning mode - // The default value for ratio is 0.01 (1 per cent). - // In case the ratio specified is such that less than 2 entries - // participate to the learning, a minimum of 2 entries are used. + //update pointer to current Tree and recompute pointers to the branches in the cache - fgLearnRatio = ratio; + fTree = tree; + Prefetch(0,0); + + fEntryMin = 0; + fEntryMax = fTree->GetEntries(); + fEntryNext = fEntryMin + fgLearnEntries; + fZipBytes = 0; + fNbranches = 0; + TIter next(fBrNames); + TObjString *os; + while ((os = (TObjString*)next())) { + TBranch *b = fTree->GetBranch(os->GetName()); + if (!b) continue; + fBranches[fNbranches] = b; + fZipBytes += b->GetZipBytes(); + fNbranches++; + } } diff --git a/treeplayer/src/TTreePlayer.cxx b/treeplayer/src/TTreePlayer.cxx index a487ddccd25..d7df35a4665 100644 --- a/treeplayer/src/TTreePlayer.cxx +++ b/treeplayer/src/TTreePlayer.cxx @@ -1,4 +1,4 @@ -// @(#)root/treeplayer:$Name: $:$Id: TTreePlayer.cxx,v 1.213 2006/06/12 09:02:03 brun Exp $ +// @(#)root/treeplayer:$Name: $:$Id: TTreePlayer.cxx,v 1.214 2006/06/14 13:15:55 brun Exp $ // Author: Rene Brun 12/01/96 /************************************************************************* @@ -2521,7 +2521,6 @@ Long64_t TTreePlayer::Process(const char *filename,Option_t *option, Long64_t ne // h2->Process("h1test.C+"); //} - DeleteSelectorFromFile(); //delete previous selector if any // This might reloads the script and delete your option -- GitLab