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