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