ROOT  6.06/09
Reference Guide
TTreeCache.cxx
Go to the documentation of this file.
1 // @(#)root/tree:$Id$
2 // Author: Rene Brun 04/06/2006
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, 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 TTreeCache
13 A specialized TFileCacheRead object for a TTree.
14 
15 This class acts as a file cache, registering automatically the baskets from
16 the branches being processed (TTree::Draw or TTree::Process and TSelectors)
17 when in the learning phase. The learning phase is by default 100 entries.
18 It can be changed via TTreeCache::SetLearnEntries.
19 
20 This cache speeds-up considerably the performance, in particular
21 when the Tree is accessed remotely via a high latency network.
22 
23 The default cache size (10 Mbytes) may be changed via the function
24 TTree::SetCacheSize
25 
26 Only the baskets for the requested entry range are put in the cache
27 
28 For each Tree being processed a TTreeCache object is created.
29 This object is automatically deleted when the Tree is deleted or
30 when the file is deleted.
31 
32 - Special case of a TChain
33  Once the training is done on the first Tree, the list of branches
34  in the cache is kept for the following files.
35 
36 - Special case of a TEventlist
37  if the Tree or TChain has a TEventlist, only the buffers
38  referenced by the list are put in the cache.
39 
40 The learning period is started or restarted when:
41  - TTree automatically creates a cache. This feature can be
42  controlled with an env. variable or the TTreeCache.Size option.
43  - TTree::SetCacheSize is called with a non-zero size and a cache
44  did not previously exist
45  - TTreeCache::StartLearningPhase is called.
46  - TTree[Cache]::SetEntryRange is called
47  * and the learning is not yet finished
48  * and has not been set to manual
49  * and the new minimun entry is different.
50 
51 The learning period is stopped (and prefetching is actually started) when:
52  - TTree[Cache]::StopLearningPhase is called.
53  - An entry outside the 'learning' range is requested
54  The 'learning range is from fEntryMin (default to 0) to
55  fEntryMin + fgLearnEntries (default to 100).
56  - A 'cached' TChain switches over to a new file.
57 
58 ## WHY DO WE NEED the TreeCache when doing data analysis?
59 
60 When writing a TTree, the branch buffers are kept in memory.
61 A typical branch buffersize (before compression) is typically 32 KBytes.
62 After compression, the zipped buffer may be just a few Kbytes.
63 The branch buffers cannot be much larger in case of Trees with several
64 hundred or thousand branches.
65 
66 When writing, this does not generate a performance problem because branch
67 buffers are always written sequentially and the OS is in general clever enough
68 to flush the data to the output file when a few MBytes of data have to be written.
69 When reading at the contrary, one may hit a performance problem when reading
70 across a network (LAN or WAN) and the network latency is high.
71 For example in a WAN with 10ms latency, reading 1000 buffers of 10 KBytes each
72 with no cache will imply 10s penalty where a local read of the 10 MBytes would
73 take about 1 second.
74 
75 The TreeCache will try to prefetch all the buffers for the selected branches
76 such that instead of transfering 1000 buffers of 10 Kbytes, it will be able
77 to transfer one single large buffer of 10 Mbytes in one single transaction.
78 Not only the TreeCache minimizes the number of transfers, but in addition
79 it can sort the blocks to be read in increasing order such that the file
80 is read sequentially.
81 
82 Systems like xrootd, dCache or httpd take advantage of the TreeCache in
83 reading ahead as much data as they can and return to the application
84 the maximum data specified in the cache and have the next chunk of data ready
85 when the next request comes.
86 
87 ## HOW TO USE the TreeCache
88 
89 A few use cases are discussed below. A cache may be created with automatic sizing
90 when a TTree is used:
91 
92 Caches are created and automatically sized for TTrees when TTreeCache.Size or
93 the environment variable ROOT_TTREECACHE_SIZE is set to a sizing factor.
94 
95 But there are many possible configurations where manual control may be wanted.
96 In some applications you know a priori the list of branches to read. In other
97 applications the analysis loop calls several layers of user functions where it
98 is impossible to predict a priori which branches will be used. This
99 is probably the most frequent case. In this case ROOT I/O will flag used
100 branches automatically when a branch buffer is read during the learning phase.
101 The TreeCache interface provides functions to instruct the cache about the used
102 branches if they are known a priori. In the examples below, portions of analysis
103 code are shown. The few statements involving the TreeCache are marked with `//<<<`
104 
105 ### 1. with TTree::Draw
106 
107 the TreeCache is automatically used by TTree::Draw. The function knows
108 which branches are used in the query and it puts automatically these branches
109 in the cache. The entry range is also known automatically.
110 
111 ### 2. with TTree::Process and TSelectors
112 
113 You must enable the cache and tell the system which branches to cache
114 and also specify the entry range. It is important to specify the entry range
115 in case you process only a subset of the events, otherwise you run the risk
116 to store in the cache entries that you do not need.
117 
118 #### example 2a
119 ~~~ {.cpp}
120  TTree *T = (TTree*)f->Get("mytree");
121  Long64_t nentries = T->GetEntries();
122  Int_t cachesize = 10000000; //10 MBytes
123  T->SetCacheSize(cachesize); //<<<
124  T->AddBranchToCache("*",kTRUE); //<<< add all branches to the cache
125  T->Process('myselector.C+");
126  //in the TSelector::Process function we read all branches
127  T->GetEntry(i);
128  ... here you process your entry
129 ~~~
130 #### example 2b
131 
132 in the Process function we read a subset of the branches.
133 Only the branches used in the first entry will be put in the cache
134 ~~~ {.cpp}
135  TTree *T = (TTree*)f->Get("mytree");
136  //we want to process only the 200 first entries
137  Long64_t nentries=200;
138  int efirst= 0;
139  int elast = efirst+nentries;
140  Int_t cachesize = 10000000; //10 MBytes
141  TTreeCache::SetLearnEntries(1); //<<< we can take the decision after 1 entry
142  T->SetCacheSize(cachesize); //<<<
143  T->SetCacheEntryRange(efirst,elast); //<<<
144  T->Process('myselector.C+","",nentries,efirst);
145  // in the TSelector::Process we read only 2 branches
146  TBranch *b1 = T->GetBranch("branch1");
147  b1->GetEntry(i);
148  if (somecondition) return;
149  TBranch *b2 = T->GetBranch("branch2");
150  b2->GetEntry(i);
151  ... here you process your entry
152 ~~~
153 ### 3. with your own event loop
154 
155 #### example 3a
156 
157 in your analysis loop, you always use 2 branches. You want to prefetch
158 the branch buffers for these 2 branches only.
159 ~~~ {.cpp}
160  TTree *T = (TTree*)f->Get("mytree");
161  TBranch *b1 = T->GetBranch("branch1");
162  TBranch *b2 = T->GetBranch("branch2");
163  Long64_t nentries = T->GetEntries();
164  Int_t cachesize = 10000000; //10 MBytes
165  T->SetCacheSize(cachesize); //<<<
166  T->AddBranchToCache(b1,kTRUE); //<<<add branch1 and branch2 to the cache
167  T->AddBranchToCache(b2,kTRUE); //<<<
168  T->StopCacheLearningPhase(); //<<<
169  for (Long64_t i=0;i<nentries;i++) {
170  T->LoadTree(i); //<<< important call when calling TBranch::GetEntry after
171  b1->GetEntry(i);
172  if (some condition not met) continue;
173  b2->GetEntry(i);
174  if (some condition not met) continue;
175  //here we read the full event only in some rare cases.
176  //there is no point in caching the other branches as it might be
177  //more economical to read only the branch buffers really used.
178  T->GetEntry(i);
179  .. process the rare but interesting cases.
180  ... here you process your entry
181  }
182 ~~~
183 #### example 3b
184 
185 in your analysis loop, you always use 2 branches in the main loop.
186 you also call some analysis functions where a few more branches will be read.
187 but you do not know a priori which ones. There is no point in prefetching
188 branches that will be used very rarely.
189 ~~~ {.cpp}
190  TTree *T = (TTree*)f->Get("mytree");
191  Long64_t nentries = T->GetEntries();
192  Int_t cachesize = 10000000; //10 MBytes
193  T->SetCacheSize(cachesize); //<<<
194  T->SetCacheLearnEntries(5); //<<< we can take the decision after 5 entries
195  TBranch *b1 = T->GetBranch("branch1");
196  TBranch *b2 = T->GetBranch("branch2");
197  for (Long64_t i=0;i<nentries;i++) {
198  T->LoadTree(i);
199  b1->GetEntry(i);
200  if (some condition not met) continue;
201  b2->GetEntry(i);
202  //at this point we may call a user function where a few more branches
203  //will be read conditionally. These branches will be put in the cache
204  //if they have been used in the first 10 entries
205  if (some condition not met) continue;
206  //here we read the full event only in some rare cases.
207  //there is no point in caching the other branches as it might be
208  //more economical to read only the branch buffers really used.
209  T->GetEntry(i);
210  .. process the rare but interesting cases.
211  ... here you process your entry
212  }
213 ~~~
214 ## SPECIAL CASES WHERE TreeCache should not be activated
215 
216 When reading only a small fraction of all entries such that not all branch
217 buffers are read, it might be faster to run without a cache.
218 
219 ## HOW TO VERIFY That the TreeCache has been used and check its performance
220 
221 Once your analysis loop has terminated, you can access/print the number
222 of effective system reads for a given file with a code like
223 (where TFile* f is a pointer to your file)
224 ~~~ {.cpp}
225  printf("Reading %lld bytes in %d transactions\n",f->GetBytesRead(), f->GetReadCalls());
226 ~~~
227 */
228 
229 #include "TSystem.h"
230 #include "TEnv.h"
231 #include "TTreeCache.h"
232 #include "TChain.h"
233 #include "TList.h"
234 #include "TBranch.h"
235 #include "TEventList.h"
236 #include "TObjString.h"
237 #include "TRegexp.h"
238 #include "TLeaf.h"
239 #include "TFriendElement.h"
240 #include "TFile.h"
241 #include <limits.h>
242 
244 
246 
247 ////////////////////////////////////////////////////////////////////////////////
248 /// Default Constructor.
249 
251  fEntryMin(0),
252  fEntryMax(1),
253  fEntryCurrent(-1),
254  fEntryNext(-1),
255  fNbranches(0),
256  fNReadOk(0),
257  fNReadMiss(0),
258  fNReadPref(0),
259  fBranches(0),
260  fBrNames(0),
261  fTree(0),
262  fIsLearning(kTRUE),
263  fIsManual(kFALSE),
264  fFirstBuffer(kTRUE),
265  fOneTime(kFALSE),
266  fReverseRead(0),
267  fFillTimes(0),
268  fFirstTime(kTRUE),
269  fFirstEntry(-1),
270  fReadDirectionSet(kFALSE),
271  fEnabled(kTRUE),
272  fPrefillType(GetConfiguredPrefillType()),
273  fAutoCreated(kFALSE)
274 {
275 }
276 
277 ////////////////////////////////////////////////////////////////////////////////
278 /// Constructor.
279 
280 TTreeCache::TTreeCache(TTree *tree, Int_t buffersize) : TFileCacheRead(tree->GetCurrentFile(),buffersize,tree),
281  fEntryMin(0),
282  fEntryMax(tree->GetEntriesFast()),
283  fEntryCurrent(-1),
284  fEntryNext(0),
285  fNbranches(0),
286  fNReadOk(0),
287  fNReadMiss(0),
288  fNReadPref(0),
289  fBranches(0),
290  fBrNames(new TList),
291  fTree(tree),
292  fIsLearning(kTRUE),
293  fIsManual(kFALSE),
294  fFirstBuffer(kTRUE),
295  fOneTime(kFALSE),
296  fReverseRead(0),
297  fFillTimes(0),
298  fFirstTime(kTRUE),
299  fFirstEntry(-1),
300  fReadDirectionSet(kFALSE),
301  fEnabled(kTRUE),
302  fPrefillType(GetConfiguredPrefillType()),
303  fAutoCreated(kFALSE)
304 {
306  Int_t nleaves = tree->GetListOfLeaves()->GetEntries();
307  fBranches = new TObjArray(nleaves);
308 }
309 
310 ////////////////////////////////////////////////////////////////////////////////
311 /// Destructor. (in general called by the TFile destructor)
312 
314 {
315  // Informe the TFile that we have been deleted (in case
316  // we are deleted explicitly by legacy user code).
317  if (fFile) fFile->SetCacheRead(0, fTree);
318 
319  delete fBranches;
320  if (fBrNames) {fBrNames->Delete(); delete fBrNames; fBrNames=0;}
321 }
322 
323 ////////////////////////////////////////////////////////////////////////////////
324 /// Add a branch to the list of branches to be stored in the cache
325 /// this function is called by TBranch::GetBasket
326 /// Returns:
327 /// - 0 branch added or already included
328 /// - -1 on error
329 
330 Int_t TTreeCache::AddBranch(TBranch *b, Bool_t subbranches /*= kFALSE*/)
331 {
332  if (!fIsLearning) {
333  return -1;
334  }
335 
336  // Reject branch that are not from the cached tree.
337  if (!b || fTree->GetTree() != b->GetTree()) return -1;
338 
339  // Is this the first addition of a branch (and we are learning and we are in
340  // the expected TTree), then prefill the cache. (We expect that in future
341  // release the Prefill-ing will be the default so we test for that inside the
342  // LearnPrefill call).
343  if (fNbranches == 0 && fEntryMin >= 0 && b->GetReadEntry() == fEntryMin) LearnPrefill();
344 
345  //Is branch already in the cache?
346  Bool_t isNew = kTRUE;
347  for (int i=0;i<fNbranches;i++) {
348  if (fBranches->UncheckedAt(i) == b) {isNew = kFALSE; break;}
349  }
350  if (isNew) {
351  fTree = b->GetTree();
352  fBranches->AddAtAndExpand(b, fNbranches);
353  fBrNames->Add(new TObjString(b->GetName()));
354  fNbranches++;
355  if (gDebug > 0) printf("Entry: %lld, registering branch: %s\n",b->GetTree()->GetReadEntry(),b->GetName());
356  }
357 
358  // process subbranches
359  Int_t res = 0;
360  if (subbranches) {
361  TObjArray *lb = b->GetListOfBranches();
362  Int_t nb = lb->GetEntriesFast();
363  for (Int_t j = 0; j < nb; j++) {
364  TBranch* branch = (TBranch*) lb->UncheckedAt(j);
365  if (!branch) continue;
366  if (AddBranch(branch, subbranches)<0) {
367  res = -1;
368  }
369  }
370  }
371  return res;
372 }
373 
374 ////////////////////////////////////////////////////////////////////////////////
375 /// Add a branch to the list of branches to be stored in the cache
376 /// this is to be used by user (thats why we pass the name of the branch).
377 /// It works in exactly the same way as TTree::SetBranchStatus so you
378 /// probably want to look over ther for details about the use of bname
379 /// with regular expressions.
380 /// The branches are taken with respect to the Owner of this TTreeCache
381 /// (i.e. the original Tree)
382 /// NB: if bname="*" all branches are put in the cache and the learning phase stopped
383 /// Returns:
384 /// - 0 branch added or already included
385 /// - -1 on error
386 
387 Int_t TTreeCache::AddBranch(const char *bname, Bool_t subbranches /*= kFALSE*/)
388 {
389  TBranch *branch, *bcount;
390  TLeaf *leaf, *leafcount;
391 
392  Int_t i;
393  Int_t nleaves = (fTree->GetListOfLeaves())->GetEntriesFast();
394  TRegexp re(bname,kTRUE);
395  Int_t nb = 0;
396  Int_t res = 0;
397 
398  // first pass, loop on all branches
399  // for leafcount branches activate/deactivate in function of status
400  Bool_t all = kFALSE;
401  if (!strcmp(bname,"*")) all = kTRUE;
402  for (i=0;i<nleaves;i++) {
403  leaf = (TLeaf*)(fTree->GetListOfLeaves())->UncheckedAt(i);
404  branch = (TBranch*)leaf->GetBranch();
405  TString s = branch->GetName();
406  if (!all) { //Regexp gives wrong result for [] in name
407  TString longname;
408  longname.Form("%s.%s",fTree->GetName(),branch->GetName());
409  if (strcmp(bname,branch->GetName())
410  && longname != bname
411  && s.Index(re) == kNPOS) continue;
412  }
413  nb++;
414  if (AddBranch(branch, subbranches)<0) {
415  res = -1;
416  }
417  leafcount = leaf->GetLeafCount();
418  if (leafcount && !all) {
419  bcount = leafcount->GetBranch();
420  if (AddBranch(bcount, subbranches)<0) {
421  res = -1;
422  }
423  }
424  }
425  if (nb==0 && strchr(bname,'*')==0) {
426  branch = fTree->GetBranch(bname);
427  if (branch) {
428  if (AddBranch(branch, subbranches)<0) {
429  res = -1;
430  }
431  ++nb;
432  }
433  }
434 
435  //search in list of friends
436  UInt_t foundInFriend = 0;
437  if (fTree->GetListOfFriends()) {
438  TIter nextf(fTree->GetListOfFriends());
439  TFriendElement *fe;
440  TString name;
441  while ((fe = (TFriendElement*)nextf())) {
442  TTree *t = fe->GetTree();
443  if (t==0) continue;
444 
445  // If the alias is present replace it with the real name.
446  char *subbranch = (char*)strstr(bname,fe->GetName());
447  if (subbranch!=bname) subbranch = 0;
448  if (subbranch) {
449  subbranch += strlen(fe->GetName());
450  if ( *subbranch != '.' ) subbranch = 0;
451  else subbranch ++;
452  }
453  if (subbranch) {
454  name.Form("%s.%s",t->GetName(),subbranch);
455  if (AddBranch(name, subbranches)<0) {
456  res = -1;
457  }
458  ++foundInFriend;
459  }
460  }
461  }
462  if (!nb && !foundInFriend) {
463  if (gDebug > 0) printf("AddBranch: unknown branch -> %s \n", bname);
464  Error("AddBranch", "unknown branch -> %s", bname);
465  return -1;
466  }
467  //if all branches are selected stop the learning phase
468  if (*bname == '*') {
469  fEntryNext = -1; // We are likely to have change the set of branches, so for the [re-]reading of the cluster.
471  }
472  return res;
473 }
474 
475 ////////////////////////////////////////////////////////////////////////////////
476 /// Remove a branch to the list of branches to be stored in the cache
477 /// this function is called by TBranch::GetBasket.
478 /// Returns:
479 /// - 0 branch dropped or not in cache
480 /// - -1 on error
481 
482 Int_t TTreeCache::DropBranch(TBranch *b, Bool_t subbranches /*= kFALSE*/)
483 {
484  if (!fIsLearning) {
485  return -1;
486  }
487 
488  // Reject branch that are not from the cached tree.
489  if (!b || fTree->GetTree() != b->GetTree()) return -1;
490 
491  //Is branch already in the cache?
492  if (fBranches->Remove(b)) {
493  --fNbranches;
494  if (gDebug > 0) printf("Entry: %lld, un-registering branch: %s\n",b->GetTree()->GetReadEntry(),b->GetName());
495  }
496  delete fBrNames->Remove(fBrNames->FindObject(b->GetName()));
497 
498  // process subbranches
499  Int_t res = 0;
500  if (subbranches) {
501  TObjArray *lb = b->GetListOfBranches();
502  Int_t nb = lb->GetEntriesFast();
503  for (Int_t j = 0; j < nb; j++) {
504  TBranch* branch = (TBranch*) lb->UncheckedAt(j);
505  if (!branch) continue;
506  if (DropBranch(branch, subbranches)<0) {
507  res = -1;
508  }
509  }
510  }
511  return res;
512 }
513 
514 ////////////////////////////////////////////////////////////////////////////////
515 /// Remove a branch to the list of branches to be stored in the cache
516 /// this is to be used by user (thats why we pass the name of the branch).
517 /// It works in exactly the same way as TTree::SetBranchStatus so you
518 /// probably want to look over ther for details about the use of bname
519 /// with regular expresions.
520 /// The branches are taken with respect to the Owner of this TTreeCache
521 /// (i.e. the original Tree)
522 /// NB: if bname="*" all branches are put in the cache and the learning phase stopped
523 /// Returns:
524 /// - 0 branch dropped or not in cache
525 /// - -1 on error
526 
527 Int_t TTreeCache::DropBranch(const char *bname, Bool_t subbranches /*= kFALSE*/)
528 {
529  TBranch *branch, *bcount;
530  TLeaf *leaf, *leafcount;
531 
532  Int_t i;
533  Int_t nleaves = (fTree->GetListOfLeaves())->GetEntriesFast();
534  TRegexp re(bname,kTRUE);
535  Int_t nb = 0;
536  Int_t res = 0;
537 
538  // first pass, loop on all branches
539  // for leafcount branches activate/deactivate in function of status
540  Bool_t all = kFALSE;
541  if (!strcmp(bname,"*")) all = kTRUE;
542  for (i=0;i<nleaves;i++) {
543  leaf = (TLeaf*)(fTree->GetListOfLeaves())->UncheckedAt(i);
544  branch = (TBranch*)leaf->GetBranch();
545  TString s = branch->GetName();
546  if (!all) { //Regexp gives wrong result for [] in name
547  TString longname;
548  longname.Form("%s.%s",fTree->GetName(),branch->GetName());
549  if (strcmp(bname,branch->GetName())
550  && longname != bname
551  && s.Index(re) == kNPOS) continue;
552  }
553  nb++;
554  if (DropBranch(branch, subbranches)<0) {
555  res = -1;
556  }
557  leafcount = leaf->GetLeafCount();
558  if (leafcount && !all) {
559  bcount = leafcount->GetBranch();
560  if (DropBranch(bcount, subbranches)<0) {
561  res = -1;
562  }
563  }
564  }
565  if (nb==0 && strchr(bname,'*')==0) {
566  branch = fTree->GetBranch(bname);
567  if (branch) {
568  if (DropBranch(branch, subbranches)<0) {
569  res = -1;
570  }
571  ++nb;
572  }
573  }
574 
575  //search in list of friends
576  UInt_t foundInFriend = 0;
577  if (fTree->GetListOfFriends()) {
578  TIter nextf(fTree->GetListOfFriends());
579  TFriendElement *fe;
580  TString name;
581  while ((fe = (TFriendElement*)nextf())) {
582  TTree *t = fe->GetTree();
583  if (t==0) continue;
584 
585  // If the alias is present replace it with the real name.
586  char *subbranch = (char*)strstr(bname,fe->GetName());
587  if (subbranch!=bname) subbranch = 0;
588  if (subbranch) {
589  subbranch += strlen(fe->GetName());
590  if ( *subbranch != '.' ) subbranch = 0;
591  else subbranch ++;
592  }
593  if (subbranch) {
594  name.Form("%s.%s",t->GetName(),subbranch);
595  if (DropBranch(name, subbranches)<0) {
596  res = -1;
597  }
598  ++foundInFriend;
599  }
600  }
601  }
602  if (!nb && !foundInFriend) {
603  if (gDebug > 0) printf("DropBranch: unknown branch -> %s \n", bname);
604  Error("DropBranch", "unknown branch -> %s", bname);
605  return -1;
606  }
607  //if all branches are selected stop the learning phase
608  if (*bname == '*') {
609  fEntryNext = -1; // We are likely to have change the set of branches, so for the [re-]reading of the cluster.
610  }
611  return res;
612 }
613 
614 ////////////////////////////////////////////////////////////////////////////////
615 /// Fill the cache buffer with the branches in the cache.
616 
618 {
619  if (fNbranches <= 0) return kFALSE;
620  TTree *tree = ((TBranch*)fBranches->UncheckedAt(0))->GetTree();
621  Long64_t entry = tree->GetReadEntry();
622  Long64_t fEntryCurrentMax = 0;
623 
624  if (fEnablePrefetching) { // Prefetching mode
625  if (fIsLearning) { // Learning mode
626  if (fEntryNext >= 0 && entry >= fEntryNext) {
627  // entry is outside the learn range, need to stop the learning
628  // phase. Doing so may trigger a recursive call to FillBuffer in
629  // the process of filling both prefetching buffers
631  fIsManual = kFALSE;
632  }
633  }
634  if (fIsLearning) { // Learning mode
635  entry = 0;
636  }
637  if (fFirstTime) {
638  //try to detect if it is normal or reverse read
639  fFirstEntry = entry;
640  }
641  else {
642  if (fFirstEntry == entry) return kFALSE;
643  // Set the read direction
644  if (!fReadDirectionSet) {
645  if (entry < fFirstEntry) {
648  }
649  else if (entry > fFirstEntry) {
652  }
653  }
654 
655  if (fReverseRead) {
656  // Reverse reading with prefetching
657  if (fEntryCurrent >0 && entry < fEntryNext) {
658  // We can prefetch the next buffer
659  if (entry >= fEntryCurrent) {
660  entry = fEntryCurrent - tree->GetAutoFlush() * fFillTimes;
661  }
662  if (entry < 0) entry = 0;
663  }
664  else if (fEntryCurrent >= 0) {
665  // We are still reading from the oldest buffer, no need to prefetch a new one
666  return kFALSE;
667  }
668  if (entry < 0) return kFALSE;
670  }
671  else {
672  // Normal reading with prefetching
673  if (fEnablePrefetching) {
674  if (entry < 0 && fEntryNext > 0) {
675  entry = fEntryCurrent;
676  } else if (entry >= fEntryCurrent) {
677  if (entry < fEntryNext) {
678  entry = fEntryNext;
679  }
680  }
681  else {
682  // We are still reading from the oldest buffer,
683  // no need to prefetch a new one
684  return kFALSE;
685  }
687  }
688  }
689  }
690  }
691 
692  // If the entry is in the range we previously prefetched, there is
693  // no point in retrying. Note that this will also return false
694  // during the training phase (fEntryNext is then set intentional to
695  // the end of the training phase).
696  if (fEntryCurrent <= entry && entry < fEntryNext) return kFALSE;
697 
698  // Triggered by the user, not the learning phase
699  if (entry == -1) entry = 0;
700 
701  fEntryCurrentMax = fEntryCurrent;
702  TTree::TClusterIterator clusterIter = tree->GetClusterIterator(entry);
703  fEntryCurrent = clusterIter();
704  fEntryNext = clusterIter.GetNextEntry();
705 
707  if (fEntryMax <= 0) fEntryMax = tree->GetEntries();
709 
710  if ( fEnablePrefetching ) {
711  if ( entry == fEntryMax ) {
712  // We are at the end, no need to do anything else
713  return kFALSE;
714  }
715  }
716 
717  // Check if owner has a TEventList set. If yes we optimize for this
718  // Special case reading only the baskets containing entries in the
719  // list.
720  TEventList *elist = fTree->GetEventList();
721  Long64_t chainOffset = 0;
722  if (elist) {
723  if (fTree->IsA() ==TChain::Class()) {
724  TChain *chain = (TChain*)fTree;
725  Int_t t = chain->GetTreeNumber();
726  chainOffset = chain->GetTreeOffset()[t];
727  }
728  }
729 
730  //clear cache buffer
731  Int_t fNtotCurrentBuf = 0;
732  if (fEnablePrefetching){ //prefetching mode
733  if (fFirstBuffer) {
735  fNtotCurrentBuf = fNtot;
736  }
737  else {
739  fNtotCurrentBuf = fBNtot;
740  }
741  }
742  else {
744  fNtotCurrentBuf = fNtot;
745  }
746 
747  //store baskets
748  Int_t clusterIterations = 0;
749  Long64_t minEntry = fEntryCurrent;
750  Int_t prevNtot;
751  Int_t minBasket = 0; // We will use this to avoid re-checking the first baskets in the 2nd (or more) run in the while loop.
752  Long64_t maxReadEntry = minEntry; // If we are stopped before the end of the 2nd pass, this marker will where we need to start next time.
753  do {
754  prevNtot = fNtotCurrentBuf;
755  Int_t nextMinBasket = INT_MAX;
756  UInt_t pass = 0;
757  while (pass < 2) {
758  // The first pass we add one basket per branches.
759  // then in the second pass we add the other baskets of the cluster.
760  // This is to support the case where the cache is too small to hold a full cluster.
761  ++pass;
762  for (Int_t i=0;i<fNbranches;i++) {
764  if (b->GetDirectory()==0) continue;
765  if (b->GetDirectory()->GetFile() != fFile) continue;
766  Int_t nb = b->GetMaxBaskets();
767  Int_t *lbaskets = b->GetBasketBytes();
768  Long64_t *entries = b->GetBasketEntry();
769  if (!lbaskets || !entries) continue;
770  //we have found the branch. We now register all its baskets
771  //from the requested offset to the basket below fEntrymax
772  Int_t blistsize = b->GetListOfBaskets()->GetSize();
773  Int_t j=minBasket; // We need this out of the loop so we can find out how far we went.
774  Bool_t firstBasketSeen = kFALSE;
775  for (;j<nb;j++) {
776  // This basket has already been read, skip it
777  if (j<blistsize && b->GetListOfBaskets()->UncheckedAt(j)) continue;
778 
779  Long64_t pos = b->GetBasketSeek(j);
780  Int_t len = lbaskets[j];
781  if (pos <= 0 || len <= 0) continue;
782  if (len > fBufferSizeMin) {
783  // Do not cache a basket if it is bigger than the cache size!
784  continue;
785  }
786  //important: do not try to read fEntryNext, otherwise you jump to the next autoflush
787  if (entries[j] >= fEntryNext) break; // break out of the for each branch loop.
788  if (entries[j] < minEntry && (j<nb-1 && entries[j+1] <= minEntry)) continue;
789  if (elist) {
790  Long64_t emax = fEntryMax;
791  if (j<nb-1) emax = entries[j+1]-1;
792  if (!elist->ContainsRange(entries[j]+chainOffset,emax+chainOffset)) continue;
793  }
794  if (pass==2 && !firstBasketSeen) {
795  // Okay, this has already been requested in the first pass.
796  firstBasketSeen = kTRUE;
797  continue;
798  }
799  fNReadPref++;
800 
801  if ( (fNtotCurrentBuf+len) > fBufferSizeMin ) {
802  // Humm ... we are going to go over the requested size.
803  if (clusterIterations > 0) {
804  // We already have a full cluster and now we would go over the requested
805  // size, let's stop caching (and make sure we start next time from the
806  // end of the previous cluster).
807  if (gDebug > 5) {
808  Info("FillBuffer","Breaking early because %d is greater than %d at cluster iteration %d will restart at %lld",(fNtotCurrentBuf+len), fBufferSizeMin, clusterIterations,minEntry);
809  }
810  fEntryNext = minEntry;
811  break;
812  } else {
813  if (pass == 1) {
814  if ( (fNtotCurrentBuf+len) > 4*fBufferSizeMin ) {
815  // Okay, so we have not even made one pass and we already have
816  // accumulated request for more than twice the memory size ...
817  // So stop for now, and will restart at the same point, hoping
818  // that the basket will still be in memory and not asked again ..
819  fEntryNext = maxReadEntry;
820  if (gDebug > 5) {
821  Info("FillBuffer","Breaking early because %d is greater than 2*%d at cluster iteration %d pass %d will restart at %lld",(fNtotCurrentBuf+len), fBufferSizeMin, clusterIterations,pass,fEntryNext);
822  }
823  break;
824  }
825  } else {
826  // We have made one pass through the branches and thus already
827  // requested one basket per branch, let's stop prefetching
828  // now.
829  if ( (fNtotCurrentBuf+len) > 2*fBufferSizeMin ) {
830  fEntryNext = maxReadEntry;
831  if (gDebug > 5) {
832  Info("FillBuffer","Breaking early because %d is greater than 2*%d at cluster iteration %d pass %d will restart at %lld",(fNtotCurrentBuf+len), fBufferSizeMin, clusterIterations,pass,fEntryNext);
833  }
834  break;
835  }
836  }
837  }
838  }
839  if (fEnablePrefetching){
840  if (fFirstBuffer) {
841  TFileCacheRead::Prefetch(pos,len);
842  fNtotCurrentBuf = fNtot;
843  }
844  else {
846  fNtotCurrentBuf = fBNtot;
847  }
848  }
849  else {
850  TFileCacheRead::Prefetch(pos,len);
851  fNtotCurrentBuf = fNtot;
852  }
853  if ( ( j < (nb-1) ) && entries[j+1] > maxReadEntry ) {
854  maxReadEntry = entries[j+1];
855  }
856  if (fNtotCurrentBuf > 4*fBufferSizeMin) {
857  // Humm something wrong happened.
858  Warning("FillBuffer","There is more data in this cluster (starting at entry %lld to %lld, current=%lld) than usual ... with %d %.3f%% of the branches we already have %d bytes (instead of %d)",
859  fEntryCurrent,fEntryNext, entries[j], i, (100.0*i) / ((float)fNbranches), fNtotCurrentBuf,fBufferSizeMin);
860 
861  }
862  if (pass==1) {
863  // In the first pass, we record one basket per branch and move on to the next branch.
864  break;
865  }
866  }
867 
868  if (j < nextMinBasket) nextMinBasket = j;
869  if (gDebug > 0) printf("Entry: %lld, registering baskets branch %s, fEntryNext=%lld, fNseek=%d, fNtotCurrentBuf=%d\n",minEntry,((TBranch*)fBranches->UncheckedAt(i))->GetName(),fEntryNext,fNseek,fNtotCurrentBuf);
870  }
871  } // loop for the 2 passes.
872  clusterIterations++;
873 
874  minEntry = clusterIter.Next();
875  if (fIsLearning) {
876  fFillTimes++;
877  }
878 
879  // Continue as long as we still make progress (prevNtot < fNtotCurrentBuf), that the next entry range to be looked at,
880  // which start at 'minEntry', is not past the end of the requested range (minEntry < fEntryMax)
881  // and we guess that we not going to go over the requested amount of memory by asking for another set
882  // of entries (fBufferSizeMin > ((Long64_t)fNtotCurrentBuf*(clusterIterations+1))/clusterIterations).
883  // fNtotCurrentBuf / clusterIterations is the average size we are accumulated so far at each loop.
884  // and thus (fNtotCurrentBuf / clusterIterations) * (clusterIterations+1) is a good guess at what the next total size
885  // would be if we run the loop one more time. fNtotCurrentBuf and clusterIterations are Int_t but can sometimes
886  // be 'large' (i.e. 30Mb * 300 intervals) and can overflow the numercial limit of Int_t (i.e. become
887  // artificially negative). To avoid this issue we promote fNtotCurrentBuf to a long long (64 bits rather than 32 bits)
888  if (!((fBufferSizeMin > ((Long64_t)fNtotCurrentBuf*(clusterIterations+1))/clusterIterations) && (prevNtot < fNtotCurrentBuf) && (minEntry < fEntryMax)))
889  break;
890 
891  //for the reverse reading case
892  if (!fIsLearning && fReverseRead){
893  if (clusterIterations >= fFillTimes)
894  break;
895  if (minEntry >= fEntryCurrentMax && fEntryCurrentMax >0)
896  break;
897  }
898  minBasket = nextMinBasket;
899  fEntryNext = clusterIter.GetNextEntry();
901  } while (kTRUE);
902 
903  if (fEnablePrefetching) {
904  if (fIsLearning) {
906  }
907  if (!fIsLearning && fFirstTime){
908  // First time we add autoFlush entries , after fFillTimes * autoFlush
909  // only in reverse prefetching mode
910  fFirstTime = kFALSE;
911  }
912  }
914  return kTRUE;
915 }
916 
917 ////////////////////////////////////////////////////////////////////////////////
918 /// Return the desired prefill type from the environment or resource variable
919 /// - 0 - No prefill
920 /// - 1 - All branches
921 
923 {
924  const char *stcp;
925  Int_t s = 0;
926 
927  if (!(stcp = gSystem->Getenv("ROOT_TTREECACHE_PREFILL")) || !*stcp) {
928  s = gEnv->GetValue("TTreeCache.Prefill", 1);
929  } else {
930  s = TString(stcp).Atoi();
931  }
932 
933  return static_cast<TTreeCache::EPrefillType>(s);
934 }
935 
936 ////////////////////////////////////////////////////////////////////////////////
937 /// Give the total efficiency of the cache... defined as the ratio
938 /// of blocks found in the cache vs. the number of blocks prefetched
939 /// ( it could be more than 1 if we read the same block from the cache more
940 /// than once )
941 ///
942 /// Note: This should eb used at the end of the processing or we will
943 /// get uncomplete stats
944 
946 {
947  if ( !fNReadPref )
948  return 0;
949 
950  return ((Double_t)fNReadOk / (Double_t)fNReadPref);
951 }
952 
953 ////////////////////////////////////////////////////////////////////////////////
954 /// This will indicate a sort of relative efficiency... a ratio of the
955 /// reads found in the cache to the number of reads so far
956 
958 {
959  if ( !fNReadOk && !fNReadMiss )
960  return 0;
961 
962  return ((Double_t)fNReadOk / (Double_t)(fNReadOk + fNReadMiss));
963 }
964 
965 ////////////////////////////////////////////////////////////////////////////////
966 /// Static function returning the number of entries used to train the cache
967 /// see SetLearnEntries
968 
970 {
971  return fgLearnEntries;
972 }
973 
974 ////////////////////////////////////////////////////////////////////////////////
975 /// Print cache statistics. Like:
976 ///
977 /// ~~~ {.cpp}
978 /// ******TreeCache statistics for file: cms2.root ******
979 /// Number of branches in the cache ...: 1093
980 /// Cache Efficiency ..................: 0.997372
981 /// Cache Efficiency Rel...............: 1.000000
982 /// Learn entries......................: 100
983 /// Reading............................: 72761843 bytes in 7 transactions
984 /// Readahead..........................: 256000 bytes with overhead = 0 bytes
985 /// Average transaction................: 10394.549000 Kbytes
986 /// Number of blocks in current cache..: 210, total size: 6280352
987 /// ~~~
988 ///
989 /// - if option = "a" the list of blocks in the cache is printed
990 /// see also class TTreePerfStats.
991 /// - if option contains 'cachedbranches', the list of branches being
992 /// cached is printed.
993 
994 void TTreeCache::Print(Option_t *option) const
995 {
996  TString opt = option;
997  opt.ToLower();
998  printf("******TreeCache statistics for tree: %s in file: %s ******\n",fTree ? fTree->GetName() : "no tree set",fFile ? fFile->GetName() : "no file set");
999  if (fNbranches <= 0) return;
1000  printf("Number of branches in the cache ...: %d\n",fNbranches);
1001  printf("Cache Efficiency ..................: %f\n",GetEfficiency());
1002  printf("Cache Efficiency Rel...............: %f\n",GetEfficiencyRel());
1003  printf("Learn entries......................: %d\n",TTreeCache::GetLearnEntries());
1004  if ( opt.Contains("cachedbranches") ) {
1005  opt.ReplaceAll("cachedbranches","");
1006  printf("Cached branches....................:\n");
1007  const TObjArray *cachedBranches = this->GetCachedBranches();
1008  Int_t nbranches = cachedBranches->GetEntriesFast();
1009  for (Int_t i = 0; i < nbranches; ++i) {
1010  TBranch* branch = (TBranch*) cachedBranches->UncheckedAt(i);
1011  printf("Branch name........................: %s\n",branch->GetName());
1012  }
1013  }
1014  TFileCacheRead::Print(opt);
1015 }
1016 
1017 ////////////////////////////////////////////////////////////////////////////////
1018 /// Old method ReadBuffer before the addition of the prefetch mechanism.
1019 
1021  //Is request already in the cache?
1022  if (TFileCacheRead::ReadBuffer(buf,pos,len) == 1){
1023  fNReadOk++;
1024  return 1;
1025  }
1026 
1027  //not found in cache. Do we need to fill the cache?
1028  Bool_t bufferFilled = FillBuffer();
1029  if (bufferFilled) {
1030  Int_t res = TFileCacheRead::ReadBuffer(buf,pos,len);
1031 
1032  if (res == 1)
1033  fNReadOk++;
1034  else if (res == 0)
1035  fNReadMiss++;
1036 
1037  return res;
1038  }
1039  fNReadMiss++;
1040 
1041  return 0;
1042 }
1043 
1044 ////////////////////////////////////////////////////////////////////////////////
1045 /// Used to read a chunk from a block previously fetched. It will call FillBuffer
1046 /// even if the cache lookup succeeds, because it will try to prefetch the next block
1047 /// as soon as we start reading from the current block.
1048 
1050  if (TFileCacheRead::ReadBuffer(buf, pos, len) == 1){
1051  //call FillBuffer to prefetch next block if necessary
1052  //(if we are currently reading from the last block available)
1053  FillBuffer();
1054  fNReadOk++;
1055  return 1;
1056  }
1057 
1058  //keep on prefetching until request is satisfied
1059  // try to prefetch a couple of times and if request is still not satisfied then
1060  // fall back to normal reading without prefetching for the current request
1061  Int_t counter = 0;
1062  while (1) {
1063  if(TFileCacheRead::ReadBuffer(buf, pos, len)) {
1064  break;
1065  }
1066  FillBuffer();
1067  fNReadMiss++;
1068  counter++;
1069  if (counter>1) {
1070  return 0;
1071  }
1072  }
1073 
1074  fNReadOk++;
1075  return 1;
1076 }
1077 
1078 ////////////////////////////////////////////////////////////////////////////////
1079 /// Read buffer at position pos if the request is in the list of
1080 /// prefetched blocks read from fBuffer.
1081 /// Otherwise try to fill the cache from the list of selected branches,
1082 /// and recheck if pos is now in the list.
1083 /// Returns:
1084 /// - -1 in case of read failure,
1085 /// - 0 in case not in cache,
1086 /// - 1 in case read from cache.
1087 /// This function overloads TFileCacheRead::ReadBuffer.
1088 
1090 {
1091  if (!fEnabled) return 0;
1092 
1093  if (fEnablePrefetching)
1094  return TTreeCache::ReadBufferPrefetch(buf, pos, len);
1095  else
1096  return TTreeCache::ReadBufferNormal(buf, pos, len);
1097 }
1098 
1099 ////////////////////////////////////////////////////////////////////////////////
1100 /// This will simply clear the cache
1101 
1103 {
1105 
1106  if (fEnablePrefetching) {
1107  fFirstTime = kTRUE;
1109  }
1110 }
1111 
1112 ////////////////////////////////////////////////////////////////////////////////
1113 /// Change the underlying buffer size of the cache.
1114 /// If the change of size means some cache content is lost, or if the buffer
1115 /// is now larger, setup for a cache refill the next time there is a read
1116 /// Returns:
1117 /// - 0 if the buffer content is still available
1118 /// - 1 if some or all of the buffer content has been made unavailable
1119 /// - -1 on error
1120 
1122 {
1123  Int_t prevsize = GetBufferSize();
1124  Int_t res = TFileCacheRead::SetBufferSize(buffersize);
1125  if (res < 0) {
1126  return res;
1127  }
1128 
1129  if (res == 0 && buffersize <= prevsize) {
1130  return res;
1131  }
1132 
1133  // if content was removed from the buffer, or the buffer was enlarged then
1134  // empty the prefetch lists and prime to fill the cache again
1135 
1137  if (fEnablePrefetching) {
1139  }
1140 
1141  fEntryCurrent = -1;
1142  if (!fIsLearning) {
1143  fEntryNext = -1;
1144  }
1145 
1146  return 1;
1147 }
1148 
1149 ////////////////////////////////////////////////////////////////////////////////
1150 /// Set the minimum and maximum entry number to be processed
1151 /// this information helps to optimize the number of baskets to read
1152 /// when prefetching the branch buffers.
1153 
1155 {
1156  // This is called by TTreePlayer::Process in an automatic way...
1157  // don't restart it if the user has specified the branches.
1158  Bool_t needLearningStart = (fEntryMin != emin) && fIsLearning && !fIsManual;
1159 
1160  fEntryMin = emin;
1161  fEntryMax = emax;
1163  if (gDebug > 0)
1164  Info("SetEntryRange", "fEntryMin=%lld, fEntryMax=%lld, fEntryNext=%lld",
1166 
1167  if (needLearningStart) {
1168  // Restart learning
1170  }
1171 }
1172 
1173 ////////////////////////////////////////////////////////////////////////////////
1174 /// Overload to make sure that the object specific
1175 
1177 {
1178  // The infinite recursion is 'broken' by the fact that
1179  // TFile::SetCacheRead remove the entry from fCacheReadMap _before_
1180  // calling SetFile (and also by setting fFile to zero before the calling).
1181  if (fFile) {
1182  TFile *prevFile = fFile;
1183  fFile = 0;
1184  prevFile->SetCacheRead(0, fTree, action);
1185  }
1186  TFileCacheRead::SetFile(file, action);
1187 }
1188 
1189 ////////////////////////////////////////////////////////////////////////////////
1190 /// Static function to set the number of entries to be used in learning mode
1191 /// The default value for n is 10. n must be >= 1
1192 
1194 {
1195  if (n < 1) n = 1;
1196  fgLearnEntries = n;
1197 }
1198 
1199 ////////////////////////////////////////////////////////////////////////////////
1200 /// Set whether the learning period is started with a prefilling of the
1201 /// cache and which type of prefilling is used.
1202 /// The two value currently supported are:
1203 /// - TTreeCache::kNoPrefill disable the prefilling
1204 /// - TTreeCache::kAllBranches fill the cache with baskets from all branches.
1205 /// The default prefilling behavior can be controlled by setting
1206 /// TTreeCache.Prefill or the environment variable ROOT_TTREECACHE_PREFILL.
1207 
1209 {
1210  fPrefillType = type;
1211 }
1212 
1213 ////////////////////////////////////////////////////////////////////////////////
1214 /// The name should be enough to explain the method.
1215 /// The only additional comments is that the cache is cleaned before
1216 /// the new learning phase.
1217 
1219 {
1220  fIsLearning = kTRUE;
1221  fIsManual = kFALSE;
1222  fNbranches = 0;
1223  if (fBrNames) fBrNames->Delete();
1225  fEntryCurrent = -1;
1226 }
1227 
1228 ////////////////////////////////////////////////////////////////////////////////
1229 /// This is the counterpart of StartLearningPhase() and can be used to stop
1230 /// the learning phase. It's useful when the user knows exactly what branches
1231 /// they are going to use.
1232 /// For the moment it's just a call to FillBuffer() since that method
1233 /// will create the buffer lists from the specified branches.
1234 
1236 {
1237  if (fIsLearning) {
1238  // This will force FillBuffer to read the buffers.
1239  fEntryNext = -1;
1240  fIsLearning = kFALSE;
1241  }
1242  fIsManual = kTRUE;
1243 
1244  //fill the buffers only once during learning
1245  if (fEnablePrefetching && !fOneTime) {
1246  fIsLearning = kTRUE;
1247  FillBuffer();
1248  fOneTime = kTRUE;
1249  }
1250 }
1251 
1252 ////////////////////////////////////////////////////////////////////////////////
1253 /// Update pointer to current Tree and recompute pointers to the branches in the cache.
1254 
1256 {
1257 
1258  fTree = tree;
1259 
1260  fEntryMin = 0;
1261  fEntryMax = fTree->GetEntries();
1262 
1263  fEntryCurrent = -1;
1264 
1265  if (fBrNames->GetEntries() == 0 && fIsLearning) {
1266  // We still need to learn.
1268  } else {
1269  // We learnt from a previous file.
1270  fIsLearning = kFALSE;
1271  fEntryNext = -1;
1272  }
1273  fNbranches = 0;
1274 
1275  TIter next(fBrNames);
1276  TObjString *os;
1277  while ((os = (TObjString*)next())) {
1278  TBranch *b = fTree->GetBranch(os->GetName());
1279  if (!b) {
1280  continue;
1281  }
1282  fBranches->AddAt(b, fNbranches);
1283  fNbranches++;
1284  }
1285 }
1286 
1287 ////////////////////////////////////////////////////////////////////////////////
1288 /// Perform an initial prefetch, attempting to read as much of the learning
1289 /// phase baskets for all branches at once
1290 
1292 {
1293  // This is meant for the learning phase
1294  if (!fIsLearning) return;
1295 
1296  // This should be called before reading entries, otherwise we'll
1297  // always exit here, since TBranch adds itself before reading
1298  if (fNbranches > 0) return;
1299 
1300  // Is the LearnPrefill enabled (using an Int_t here to allow for future
1301  // extension to alternative Prefilling).
1302  if (fPrefillType == kNoPrefill) return;
1303 
1304  // Force only the learn entries to be cached by temporarily setting min/max
1305  // to the learning phase entry range
1306  // But save all the old values, so we can restore everything to how it was
1307  Long64_t eminOld = fEntryMin;
1308  Long64_t emaxOld = fEntryMax;
1309  Long64_t ecurrentOld = fEntryCurrent;
1310  Long64_t enextOld = fEntryNext;
1311 
1314 
1315  // Add all branches to be cached. This also sets fIsManual, stops learning,
1316  // and makes fEntryNext = -1 (which forces a cache fill, which is good)
1317  AddBranch("*");
1318  fIsManual = kFALSE; // AddBranch sets fIsManual, so we reset it
1319 
1320  // Now, fill the buffer with the learning phase entry range
1321  FillBuffer();
1322 
1323  // Leave everything the way we found it
1324  fIsLearning = kTRUE;
1325  DropBranch("*"); // This doesn't work unless we're already learning
1326 
1327  // Restore entry values
1328  fEntryMin = eminOld;
1329  fEntryMax = emaxOld;
1330  fEntryCurrent = ecurrentOld;
1331  fEntryNext = enextOld;
1332 }
const char * GetName() const
Returns name of object.
Definition: TObjString.h:42
Long64_t GetReadEntry() const
Definition: TBranch.h:169
virtual Int_t GetEntries() const
Definition: TCollection.h:92
Int_t fNtot
Total size of prefetched blocks.
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:37
Long64_t fEntryMax
first entry in the cache
Definition: TTreeCache.h:41
An array of TObjects.
Definition: TObjArray.h:39
Long64_t GetNextEntry()
Definition: TTree.h:278
virtual void Delete(Option_t *option="")
Remove all objects from the list AND delete all heap based objects.
Definition: TList.cxx:404
Int_t fNReadOk
Number of branches in the cache.
Definition: TTreeCache.h:45
TFile * fFile
Pointer to file.
long long Long64_t
Definition: RtypesCore.h:69
const TObjArray * GetCachedBranches() const
Definition: TTreeCache.h:80
ClassImp(TSeqCollection) Int_t TSeqCollection TIter next(this)
Return index of object in collection.
TObjArray * GetListOfBaskets()
Definition: TBranch.h:176
Collectable string class.
Definition: TObjString.h:32
TObjArray * fBranches
Definition: TTreeCache.h:48
A cache when reading files over the network.
const char Option_t
Definition: RtypesCore.h:62
TEventList * GetEventList() const
Definition: TTree.h:392
Bool_t fOneTime
true if first buffer is used for prefetching
Definition: TTreeCache.h:54
virtual Long64_t GetReadEntry() const
Definition: TTree.h:424
virtual void SetCacheRead(TFileCacheRead *cache, TObject *tree=0, ECacheAction action=kDisconnect)
Set a pointer to the read cache.
Definition: TFile.cxx:2177
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:635
virtual void SetLearnPrefill(EPrefillType type=kNoPrefill)
Set whether the learning period is started with a prefilling of the cache and which type of prefillin...
A specialized TFileCacheRead object for a TTree.
Definition: TTreeCache.h:34
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:892
A ROOT file is a suite of consecutive data records (TKey instances) with a well defined format...
Definition: TFile.h:45
Regular expression class.
Definition: TRegexp.h:35
virtual TObject * Remove(TObject *obj)
Remove object from array.
Definition: TObjArray.cxx:652
Long64_t fEntryMin
Definition: TTreeCache.h:40
Basic string class.
Definition: TString.h:137
void ToLower()
Change string to lower-case.
Definition: TString.cxx:1088
virtual void Prefetch(Long64_t pos, Int_t len)
Add block of length len at position pos in the list of blocks to be prefetched.
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:496
TBranch * GetBranch() const
Definition: TLeaf.h:70
virtual Long64_t GetBasketSeek(Int_t basket) const
Return address of basket in the file.
Definition: TBranch.cxx:1143
virtual void StopLearningPhase()
This is the counterpart of StartLearningPhase() and can be used to stop the learning phase...
Int_t GetEntriesFast() const
Definition: TObjArray.h:66
virtual void LearnPrefill()
Perform an initial prefetch, attempting to read as much of the learning phase baskets for all branche...
TTree * GetTree() const
Definition: TTreeCache.h:88
Long64_t * GetBasketEntry() const
Definition: TBranch.h:149
void StartLearningPhase()
The name should be enough to explain the method.
virtual Int_t AddBranch(TBranch *b, Bool_t subgbranches=kFALSE)
Add a branch to the list of branches to be stored in the cache this function is called by TBranch::Ge...
Definition: TTreeCache.cxx:330
virtual void Print(Option_t *option="") const
Print cache statistics.
Definition: TTreeCache.cxx:994
virtual Int_t ReadBufferNormal(char *buf, Long64_t pos, Int_t len)
Old method ReadBuffer before the addition of the prefetch mechanism.
virtual TList * GetListOfFriends() const
Definition: TTree.h:407
Long64_t * GetTreeOffset() const
Definition: TChain.h:119
Helper class to iterate over cluster of baskets.
Definition: TTree.h:245
virtual void SecondPrefetch(Long64_t, Int_t)
void Class()
Definition: Class.C:29
virtual Int_t GetTreeNumber() const
Definition: TChain.h:118
Bool_t fIsTransferred
True when fBuffer contains something valid.
Int_t * GetBasketBytes() const
Definition: TBranch.h:148
virtual Bool_t ContainsRange(Long64_t entrymin, Long64_t entrymax)
Return TRUE if list contains entries from entrymin to entrymax included.
Definition: TEventList.cxx:169
EPrefillType GetConfiguredPrefillType() const
Return the desired prefill type from the environment or resource variable.
Definition: TTreeCache.cxx:922
virtual Int_t GetBufferSize() const
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1627
virtual TClusterIterator GetClusterIterator(Long64_t firstentry)
Return an iterator over the cluster of baskets starting at firstentry.
Definition: TTree.cxx:4995
virtual Int_t ReadBuffer(char *buf, Long64_t pos, Int_t len)
Read buffer at position pos if the request is in the list of prefetched blocks read from fBuffer...
virtual void ResetCache()
This will simply clear the cache.
Bool_t fEnabled
read direction established
Definition: TTreeCache.h:60
Int_t Atoi() const
Return integer value of string.
Definition: TString.cxx:1964
TObjArray * GetListOfBranches()
Definition: TBranch.h:177
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
A doubly linked list.
Definition: TList.h:47
virtual TBranch * GetBranch(const char *name)
Return pointer to the branch with the given name in this tree or its friends.
Definition: TTree.cxx:4822
TTree * fTree
list of branch names in the cache
Definition: TTreeCache.h:50
virtual TFile * GetFile() const
Definition: TDirectory.h:152
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:91
Double_t GetEfficiency() const
Give the total efficiency of the cache...
Definition: TTreeCache.cxx:945
virtual void SetEntryRange(Long64_t emin, Long64_t emax)
Set the minimum and maximum entry number to be processed this information helps to optimize the numbe...
virtual void AddAtAndExpand(TObject *obj, Int_t idx)
Add object at position idx.
Definition: TObjArray.cxx:221
virtual Int_t DropBranch(TBranch *b, Bool_t subbranches=kFALSE)
Remove a branch to the list of branches to be stored in the cache this function is called by TBranch:...
Definition: TTreeCache.cxx:482
R__EXTERN TSystem * gSystem
Definition: TSystem.h:549
virtual Int_t GetValue(const char *name, Int_t dflt)
Returns the integer value for a resource.
Definition: TEnv.cxx:494
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:674
virtual Int_t ReadBufferPrefetch(char *buf, Long64_t pos, Int_t len)
Used to read a chunk from a block previously fetched.
virtual ~TTreeCache()
Destructor. (in general called by the TFile destructor)
Definition: TTreeCache.cxx:313
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2321
unsigned int UInt_t
Definition: RtypesCore.h:42
virtual void Print(Option_t *option="") const
Print cache statistics.
virtual void SetFile(TFile *file, TFile::ECacheAction action=TFile::kDisconnect)
Set the file using this cache and reset the current blocks (if any).
A TEventList object is a list of selected events (entries) in a TTree.
Definition: TEventList.h:33
Bool_t fReadDirectionSet
save the value of the first entry
Definition: TTreeCache.h:59
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
Int_t fNReadMiss
Definition: TTreeCache.h:46
static void SetLearnEntries(Int_t n=10)
Static function to set the number of entries to be used in learning mode The default value for n is 1...
virtual Int_t SetBufferSize(Int_t buffersize)
Sets the buffer size.
Long64_t entry
virtual Bool_t FillBuffer()
Fill the cache buffer with the branches in the cache.
Definition: TTreeCache.cxx:617
virtual void AddAt(TObject *obj, Int_t idx)
Add object at position ids.
Definition: TObjArray.cxx:238
TTree * GetTree() const
Definition: TBranch.h:183
virtual TLeaf * GetLeafCount() const
Definition: TLeaf.h:71
Int_t fNReadPref
Definition: TTreeCache.h:47
Bool_t fReverseRead
used in the learning phase
Definition: TTreeCache.h:55
Bool_t fFirstTime
how many times we can fill the current buffer
Definition: TTreeCache.h:57
Long64_t fEntryCurrent
last entry in the cache
Definition: TTreeCache.h:42
Int_t fBufferSizeMin
Original size of fBuffer.
ClassImp(TTreeCache) TTreeCache
Default Constructor.
Definition: TTreeCache.cxx:245
Long64_t Next()
Move on to the next cluster and return the starting entry of this next cluster.
Definition: TTree.cxx:575
virtual Int_t GetSize() const
Definition: TCollection.h:95
virtual Long64_t GetAutoFlush() const
Definition: TTree.h:367
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:415
double Double_t
Definition: RtypesCore.h:55
Bool_t fIsLearning
pointer to the current Tree
Definition: TTreeCache.h:51
int type
Definition: TGX11.cxx:120
R__EXTERN TEnv * gEnv
Definition: TEnv.h:174
ClassImp(TMCParticle) void TMCParticle printf(": p=(%7.3f,%7.3f,%9.3f) ;", fPx, fPy, fPz)
virtual void SetFile(TFile *file, TFile::ECacheAction action=TFile::kDisconnect)
Overload to make sure that the object specific.
EPrefillType fPrefillType
cache enabled for cached reading
Definition: TTreeCache.h:61
virtual TTree * GetTree() const
Definition: TTree.h:432
Int_t fFillTimes
reading in reverse mode
Definition: TTreeCache.h:56
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:493
virtual Int_t SetBufferSize(Int_t buffersize)
Change the underlying buffer size of the cache.
#define name(a, b)
Definition: linkTestLib0.cpp:5
TDirectory * GetDirectory() const
Definition: TBranch.h:157
Int_t fNbranches
next entry number where cache must be filled
Definition: TTreeCache.h:44
Int_t GetMaxBaskets() const
Definition: TBranch.h:179
Bool_t fEnablePrefetching
reading by prefetching asynchronously
virtual void Add(TObject *obj)
Definition: TList.h:81
const Ssiz_t kNPOS
Definition: Rtypes.h:115
Long64_t fFirstEntry
save the fact that we processes the first entry
Definition: TTreeCache.h:58
A TFriendElement TF describes a TTree object TF in a file.
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:567
A chain is a collection of files containg TTree objects.
Definition: TChain.h:35
TList * fBrNames
List of branches to be stored in the cache.
Definition: TTreeCache.h:49
Bool_t fFirstBuffer
true if cache is StopLearningPhase was used
Definition: TTreeCache.h:53
static Int_t fgLearnEntries
Definition: TTreeCache.h:62
R__EXTERN Int_t gDebug
Definition: Rtypes.h:128
virtual Int_t ReadBuffer(char *buf, Long64_t pos, Int_t len)
Read buffer at position pos.
virtual Long64_t GetEntries() const
Definition: TTree.h:382
A TTree object has a header with a name and a title.
Definition: TTree.h:94
Bool_t fIsManual
true if cache is in learning mode
Definition: TTreeCache.h:52
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:582
A TTree is a list of TBranches.
Definition: TBranch.h:58
Long64_t fEntryNext
current lowest entry number in the cache
Definition: TTreeCache.h:43
Double_t GetEfficiencyRel() const
This will indicate a sort of relative efficiency...
Definition: TTreeCache.cxx:957
const Bool_t kTRUE
Definition: Rtypes.h:91
virtual void UpdateBranches(TTree *tree)
Update pointer to current Tree and recompute pointers to the branches in the cache.
const Int_t n
Definition: legend1.C:16
static Int_t GetLearnEntries()
Static function returning the number of entries used to train the cache see SetLearnEntries.
Definition: TTreeCache.cxx:969
Int_t fNseek
Number of blocks to be prefetched.
virtual TObjArray * GetListOfLeaves()
Definition: TTree.h:406
ECacheAction
TTreeCache flushing semantics.
Definition: TFile.h:57
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:904