Skip to content

Commit

Permalink
Add support for Bulk I/O with SetClusterPrefetch
Browse files Browse the repository at this point in the history
This fixes root-project#8962

The code pattern is similar to 0987896

  Add infrastructure for sharing memory in a TBuffer.
  • Loading branch information
pcanal committed Oct 11, 2022
1 parent 5248676 commit 29f0497
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 7 deletions.
2 changes: 1 addition & 1 deletion tree/tree/inc/TBranch.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ class TBranch : public TNamed , public TAttFill {
void Init(const char *name, const char *leaflist, Int_t compress);

TBasket *GetFreshBasket(Int_t basketnumber, TBuffer *user_buffer);
TBasket *GetFreshCluster();
TBasket *GetFreshCluster(TBuffer *user_buffer);
Int_t WriteBasket(TBasket* basket, Int_t where) { return WriteBasketImpl(basket, where, nullptr); }

TString GetRealFileName() const;
Expand Down
25 changes: 19 additions & 6 deletions tree/tree/src/TBranch.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1233,7 +1233,7 @@ TBasket* TBranch::GetBasketImpl(Int_t basketnumber, TBuffer *user_buffer)
// if cluster pre-fetching or retaining is on, do not re-use existing baskets
// unless a new cluster is used.
if (fTree->GetMaxVirtualSize() < 0 || fTree->GetClusterPrefetch())
basket = GetFreshCluster();
basket = GetFreshCluster(user_buffer);
else
basket = GetFreshBasket(basketnumber, user_buffer);

Expand Down Expand Up @@ -1835,23 +1835,36 @@ TBasket* TBranch::GetFreshBasket(Int_t basketnumber, TBuffer* user_buffer)
/// Drops the cluster two behind the current cluster and returns a fresh basket
/// by either reusing or creating a new one

TBasket *TBranch::GetFreshCluster()
TBasket *TBranch::GetFreshCluster(TBuffer* user_buffer)
{
TBasket *basket = 0;

auto CreateOrReuseBasket = [this, user_buffer]() -> TBasket* {
TBasket *newbasket = nullptr;
if (fExtraBasket) {
newbasket = fExtraBasket;
fExtraBasket = nullptr;
} else {
newbasket = fTree->CreateBasket(this);
}
if (user_buffer)
newbasket->AdoptBuffer(user_buffer);
return newbasket;
};

// If GetClusterIterator is called with a negative entry then GetStartEntry will be 0
// So we need to check if we reach the zero before we have gone back (1-VirtualSize) clusters
// if this is the case, we want to keep everything in memory so we return a new basket
TTree::TClusterIterator iter = fTree->GetClusterIterator(fBasketEntry[fReadBasket]);
if (iter.GetStartEntry() == 0) {
return fTree->CreateBasket(this);
return CreateOrReuseBasket();
}

// Iterate backwards (1-VirtualSize) clusters to reach cluster to be unloaded from memory,
// skipped if VirtualSize > 0.
for (Int_t j = 0; j < -fTree->GetMaxVirtualSize(); j++) {
if (iter.Previous() == 0) {
return fTree->CreateBasket(this);
return CreateOrReuseBasket();
}
}

Expand All @@ -1863,7 +1876,7 @@ TBasket *TBranch::GetFreshCluster()
while (fBasketEntry[basketToUnload] != entryToUnload) {
basketToUnload--;
if (basketToUnload < 0) {
return fTree->CreateBasket(this);
return CreateOrReuseBasket();
}
}

Expand All @@ -1874,7 +1887,7 @@ TBasket *TBranch::GetFreshCluster()
fBaskets.AddAt(0, basketToUnload);
--fNBaskets;
} else {
basket = fTree->CreateBasket(this);
basket = CreateOrReuseBasket();
}
++basketToUnload;

Expand Down

0 comments on commit 29f0497

Please sign in to comment.