Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RPagePool.cxx
Go to the documentation of this file.
1/// \file RPagePool.cxx
2/// \ingroup NTuple
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2018-10-04
5
6/*************************************************************************
7 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
8 * All rights reserved. *
9 * *
10 * For the licensing terms see $ROOTSYS/LICENSE. *
11 * For the list of contributors see $ROOTSYS/README/CREDITS. *
12 *************************************************************************/
13
14#include <ROOT/RPagePool.hxx>
15#include <ROOT/RPageStorage.hxx>
16#include <ROOT/RColumn.hxx>
17
18#include <TError.h>
19
20#include <algorithm>
21#include <cstdlib>
22#include <utility>
23
25{
27 fCounters = std::make_unique<RCounters>(
28 RCounters{*fMetrics.MakeCounter<RNTupleAtomicCounter *>("nPage", "", "number of currently cached pages")});
29}
30
33{
34 assert(fLookupByBuffer.count(page.GetBuffer()) == 0);
35
36 const auto entryIndex = fEntries.size();
37
38 auto itrPageSet = fLookupByKey.find(key);
39 if (itrPageSet != fLookupByKey.end()) {
40 auto [itrEntryIdx, isNew] = itrPageSet->second.emplace(RPagePosition(page), entryIndex);
41 if (!isNew) {
42 assert(itrEntryIdx->second < fEntries.size());
43 // We require that pages cover pairwise distinct element ranges of the column
44 assert(fEntries[itrEntryIdx->second].fPage.GetGlobalRangeLast() == page.GetGlobalRangeLast());
45 fEntries[itrEntryIdx->second].fRefCounter += initialRefCounter;
46 return fEntries[itrEntryIdx->second];
47 }
48 } else {
49 fLookupByKey.emplace(key, std::map<RPagePosition, std::size_t>{{RPagePosition(page), entryIndex}});
50 }
51
52 fLookupByBuffer[page.GetBuffer()] = entryIndex;
53
54 fCounters->fNPage.Inc();
55 return fEntries.emplace_back(REntry{std::move(page), key, initialRefCounter});
56}
57
59{
60 std::lock_guard<std::mutex> lockGuard(fLock);
61 return RPageRef(AddPage(std::move(page), key, 1).fPage, this);
62}
63
65{
66 std::lock_guard<std::mutex> lockGuard(fLock);
67 const auto &entry = AddPage(std::move(page), key, 0);
68 if (entry.fRefCounter == 0)
69 AddToUnusedPages(entry.fPage);
70}
71
72void ROOT::Internal::RPagePool::ErasePage(std::size_t entryIdx, decltype(fLookupByBuffer)::iterator lookupByBufferItr)
73{
74 fLookupByBuffer.erase(lookupByBufferItr);
75
76 auto itrPageSet = fLookupByKey.find(fEntries[entryIdx].fKey);
77 assert(itrPageSet != fLookupByKey.end());
78 itrPageSet->second.erase(RPagePosition(fEntries[entryIdx].fPage));
79 if (itrPageSet->second.empty())
80 fLookupByKey.erase(itrPageSet);
81
82 const auto N = fEntries.size();
83 assert(entryIdx < N);
84 if (entryIdx != (N - 1)) {
85 fLookupByBuffer[fEntries[N - 1].fPage.GetBuffer()] = entryIdx;
86 itrPageSet = fLookupByKey.find(fEntries[N - 1].fKey);
87 assert(itrPageSet != fLookupByKey.end());
88 auto itrEntryIdx = itrPageSet->second.find(RPagePosition(fEntries[N - 1].fPage));
89 assert(itrEntryIdx != itrPageSet->second.end());
90 itrEntryIdx->second = entryIdx;
91 fEntries[entryIdx] = std::move(fEntries[N - 1]);
92 }
93
94 fCounters->fNPage.Dec();
95 fEntries.resize(N - 1);
96}
97
99{
100 if (page.IsNull()) return;
101 std::lock_guard<std::mutex> lockGuard(fLock);
102
103 auto itrLookup = fLookupByBuffer.find(page.GetBuffer());
104 assert(itrLookup != fLookupByBuffer.end());
105 const auto idx = itrLookup->second;
106
107 assert(fEntries[idx].fRefCounter >= 1);
108 if (--fEntries[idx].fRefCounter == 0) {
109 if (fPageSource.GetPinnedClusters().count(page.GetClusterInfo().GetId()) > 0) {
110 AddToUnusedPages(page);
111 } else {
112 ErasePage(idx, itrLookup);
113 }
114 }
115}
116
118{
119 fUnusedPages[page.GetClusterInfo().GetId()].emplace(page.GetBuffer());
120}
121
123{
124 auto itr = fUnusedPages.find(page.GetClusterInfo().GetId());
125 assert(itr != fUnusedPages.end());
126 itr->second.erase(page.GetBuffer());
127 if (itr->second.empty())
128 fUnusedPages.erase(itr);
129}
130
132{
133 std::lock_guard<std::mutex> lockGuard(fLock);
134 auto itrPageSet = fLookupByKey.find(key);
135 if (itrPageSet == fLookupByKey.end())
136 return RPageRef();
137 assert(!itrPageSet->second.empty());
138
139 auto itrEntryIdx = itrPageSet->second.upper_bound(RPagePosition(globalIndex));
140 if (itrEntryIdx == itrPageSet->second.begin())
141 return RPageRef();
142
143 --itrEntryIdx;
144 if (fEntries[itrEntryIdx->second].fPage.Contains(globalIndex)) {
145 if (fEntries[itrEntryIdx->second].fRefCounter == 0)
146 RemoveFromUnusedPages(fEntries[itrEntryIdx->second].fPage);
147 fEntries[itrEntryIdx->second].fRefCounter++;
148 return RPageRef(fEntries[itrEntryIdx->second].fPage, this);
149 }
150 return RPageRef();
151}
152
154{
155 std::lock_guard<std::mutex> lockGuard(fLock);
156 auto itrPageSet = fLookupByKey.find(key);
157 if (itrPageSet == fLookupByKey.end())
158 return RPageRef();
159 assert(!itrPageSet->second.empty());
160
161 auto itrEntryIdx = itrPageSet->second.upper_bound(RPagePosition(localIndex));
162 if (itrEntryIdx == itrPageSet->second.begin())
163 return RPageRef();
164
165 --itrEntryIdx;
166 if (fEntries[itrEntryIdx->second].fPage.Contains(localIndex)) {
167 if (fEntries[itrEntryIdx->second].fRefCounter == 0)
168 RemoveFromUnusedPages(fEntries[itrEntryIdx->second].fPage);
169 fEntries[itrEntryIdx->second].fRefCounter++;
170 return RPageRef(fEntries[itrEntryIdx->second].fPage, this);
171 }
172 return RPageRef();
173}
174
176{
177 std::lock_guard<std::mutex> lockGuard(fLock);
178 auto itr = fUnusedPages.find(clusterId);
179 if (itr == fUnusedPages.end())
180 return;
181
182 for (auto pageBuffer : itr->second) {
183 const auto itrLookupByBuffer = fLookupByBuffer.find(pageBuffer);
184 assert(itrLookupByBuffer != fLookupByBuffer.end());
185 const auto entryIdx = itrLookupByBuffer->second;
186 assert(fEntries[entryIdx].fRefCounter == 0);
187 ErasePage(entryIdx, itrLookupByBuffer);
188 }
189
190 fUnusedPages.erase(itr);
191}
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
#define N
A thread-safe integral performance counter.
CounterPtrT MakeCounter(const std::string &name, Args &&... args)
std::unique_ptr< RCounters > fCounters
void ErasePage(std::size_t entryIdx, decltype(fLookupByBuffer)::iterator lookupByBufferItr)
Called both by ReleasePage() and by Evict() to remove an unused page from the pool.
Definition RPagePool.cxx:72
ROOT::Experimental::Detail::RNTupleMetrics fMetrics
The page pool counters are observed by the page source.
void Evict(ROOT::DescriptorId_t clusterId)
Removes unused pages (pages with reference counter 0) from the page pool.
REntry & AddPage(RPage page, const RKey &key, std::int64_t initialRefCounter)
Add a new page to the fLookupByBuffer and fLookupByKey data structures.
Definition RPagePool.cxx:32
RPageRef GetPage(RKey key, ROOT::NTupleSize_t globalIndex)
Tries to find the page corresponding to column and index in the cache.
RPagePool(RPageSource &pageSource)
Definition RPagePool.cxx:24
void AddToUnusedPages(const RPage &page)
Called by PreloadPage() if the page at hand is new and thus added with ref counter 0.
void PreloadPage(RPage page, RKey key)
Like RegisterPage() but the reference counter is initialized to 0.
Definition RPagePool.cxx:64
RPageRef RegisterPage(RPage page, RKey key)
Adds a new page to the pool.
Definition RPagePool.cxx:58
void RemoveFromUnusedPages(const RPage &page)
Called by GetPage(), when the reference counter increases from zero to one.
void ReleasePage(const RPage &page)
Give back a page to the pool and decrease the reference counter.
Definition RPagePool.cxx:98
Reference to a page stored in the page pool.
Abstract interface to read data from an ntuple.
A page is a slice of a column that is mapped into memory.
Definition RPage.hxx:44
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
const_iterator begin() const
const_iterator end() const
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
Performance counters that get registered in fMetrics.
Every page in the page pool is annotated with a search key and a reference counter.
Definition RPagePool.hxx:77
Used in fLookupByKey to store both the absolute and the cluster-local page index of the referenced pa...
Definition RPagePool.hxx:86