diff --git a/tree/ntuple/inc/ROOT/RNTupleProcessor.hxx b/tree/ntuple/inc/ROOT/RNTupleProcessor.hxx index 5598260ad3ae5..22c1d399f3ce4 100644 --- a/tree/ntuple/inc/ROOT/RNTupleProcessor.hxx +++ b/tree/ntuple/inc/ROOT/RNTupleProcessor.hxx @@ -615,9 +615,8 @@ private: /// \brief Get the total number of entries in this processor. ROOT::NTupleSize_t GetNEntries() final { - Initialize(); if (fNEntries == ROOT::kInvalidNTupleIndex) - Connect(fFieldIdxs); + Initialize(); return fNEntries; } diff --git a/tree/ntuple/src/RNTupleProcessor.cxx b/tree/ntuple/src/RNTupleProcessor.cxx index 3a00539e0a82c..077503fe2cc66 100644 --- a/tree/ntuple/src/RNTupleProcessor.cxx +++ b/tree/ntuple/src/RNTupleProcessor.cxx @@ -347,13 +347,24 @@ ROOT::Experimental::RNTupleChainProcessor::AddFieldToEntry(const std::string &fi ROOT::NTupleSize_t ROOT::Experimental::RNTupleChainProcessor::LoadEntry(ROOT::NTupleSize_t entryNumber) { - ROOT::NTupleSize_t localEntryNumber = entryNumber; - std::size_t currProcessorNumber = 0; + // If the requested entry number is lower than the current entry number, we have to again localise the correct local + // entry number starting from the first processor in the chain. Otherwise, we can continue looking from the inner + // processor that is currently connected, which is much faster when the chain consists of many inner processors. if (entryNumber < fCurrentEntryNumber) { fCurrentProcessorNumber = 0; ConnectInnerProcessor(fCurrentProcessorNumber); } + std::size_t currProcessorNumber = fCurrentProcessorNumber; + ROOT::NTupleSize_t entriesSeen = 0; + for (unsigned i = 0; i < currProcessorNumber; ++i) { + if (fInnerNEntries[i] == kInvalidNTupleIndex) { + fInnerNEntries[i] = fInnerProcessors[i]->GetNEntries(); + } + entriesSeen += fInnerNEntries[i]; + } + ROOT::NTupleSize_t localEntryNumber = entryNumber - entriesSeen; + // As long as the entry fails to load from the current processor, we decrement the local entry number with the number // of entries in this processor and try with the next processor until we find the correct local entry number. while (fInnerProcessors[currProcessorNumber]->LoadEntry(localEntryNumber) == kInvalidNTupleIndex) {