Skip to content

Commit 538b0b0

Browse files
authored
Merge a7453b1 into 9bb228f
2 parents 9bb228f + a7453b1 commit 538b0b0

11 files changed

+559
-261
lines changed

ydb/core/tablet_flat/flat_fwd_cache.h

Lines changed: 115 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,114 @@
11
#pragma once
22

33
#include "flat_part_iface.h"
4-
#include "flat_part_forward.h"
54
#include "flat_fwd_iface.h"
65
#include "flat_fwd_misc.h"
76
#include "flat_fwd_page.h"
7+
#include "flat_part_index_iter_iface.h"
8+
#include "flat_table_part.h"
9+
#include "flat_part_slice.h"
810

911
namespace NKikimr {
1012
namespace NTable {
1113
namespace NFwd {
1214

13-
class TCache : public IPageLoadingLogic {
14-
using TGroupId = NPage::TGroupId;
15-
16-
template<size_t Items>
17-
struct TRound {
18-
const TSharedData* Get(TPageId pageId) const
19-
{
20-
if (pageId < Edge) {
21-
const auto pred = [pageId](const NPageCollection::TLoadedPage &page) {
22-
return page.PageId == pageId;
23-
};
24-
25-
auto it = std::find_if(Pages.begin(), Pages.end(), pred);
26-
27-
if (it == Pages.end()) {
28-
Y_ABORT("Failed to locate page within forward trace");
15+
template<size_t Capacity>
16+
class TLoadedPagesCircularBuffer {
17+
public:
18+
const TSharedData* Get(TPageId pageId) const
19+
{
20+
if (pageId < FirstUnseenPageId) {
21+
for (const auto& page : LoadedPages) {
22+
if (page.PageId == pageId) {
23+
return &page.Data;
2924
}
30-
31-
return &it->Data;
3225
}
3326

34-
return nullptr;
27+
Y_ABORT("Failed to locate page within forward trace");
3528
}
3629

37-
ui32 Emplace(TPage &page)
38-
{
39-
Y_ABORT_UNLESS(page, "Cannot push invalid page to trace cache");
30+
// next pages may be requested, ignore them
31+
return nullptr;
32+
}
33+
34+
// returns released data size
35+
ui64 Emplace(TPage &page)
36+
{
37+
Y_ABORT_UNLESS(page, "Cannot push invalid page to trace cache");
4038

41-
Offset = (Pages.size() + Offset - 1) % Pages.size();
39+
Offset = (Offset + 1) % Capacity;
4240

43-
const ui32 was = Pages[Offset].Data.size();
41+
const ui64 releasedDataSize = LoadedPages[Offset].Data.size();
4442

45-
Pages[Offset].Data = page.Release();
46-
Pages[Offset].PageId = page.PageId;
47-
Edge = Max(Edge, page.PageId + 1);
43+
LoadedPages[Offset].Data = page.Release();
44+
LoadedPages[Offset].PageId = page.PageId;
45+
FirstUnseenPageId = Max(FirstUnseenPageId, page.PageId + 1);
4846

49-
return was;
50-
}
47+
return releasedDataSize;
48+
}
5149

52-
private:
53-
std::array<NPageCollection::TLoadedPage, Items> Pages;
54-
TPageId Edge = 0;
55-
ui32 Offset = 0;
56-
};
50+
private:
51+
std::array<NPageCollection::TLoadedPage, Capacity> LoadedPages;
52+
ui32 Offset = 0;
53+
TPageId FirstUnseenPageId = 0;
54+
};
5755

56+
class TCache : public IPageLoadingLogic {
5857
public:
58+
using TGroupId = NPage::TGroupId;
59+
5960
TCache() = delete;
6061

6162
TCache(const TPart* part, IPages* env, TGroupId groupId, const TIntrusiveConstPtr<TSlices>& bounds = nullptr)
62-
: Index(part, env, groupId, 1, bounds)
63-
{ }
63+
: Index(CreateIndexIter(part, env, groupId))
64+
{
65+
if (bounds && !bounds->empty()) {
66+
BeginRowId = bounds->front().BeginRowId();
67+
EndRowId = bounds->back().EndRowId();
68+
} else {
69+
BeginRowId = 0;
70+
EndRowId = Index->GetEndRowId();
71+
}
72+
}
6473

6574
~TCache()
6675
{
67-
for (auto &it: Pages) it.Release();
76+
for (auto &it: Pages) {
77+
it.Release();
78+
}
6879
}
6980

7081
TResult Handle(IPageLoadingQueue *head, TPageId pageId, ui64 lower) noexcept override
7182
{
72-
Y_ABORT_UNLESS(pageId != Max<TPageId>(), "Invalid requested pageId");
83+
Y_ABORT_UNLESS(pageId != Max<TPageId>(), "Requested page is invalid");
7384

74-
if (auto *page = Trace.Get(pageId))
85+
if (auto *page = Trace.Get(pageId)) {
7586
return { page, false, true };
87+
}
7688

77-
Rewind(pageId).Shrink(); /* points Offset to pageId */
89+
DropPagesBefore(pageId);
90+
Shrink();
91+
92+
bool grow = OnHold + OnFetch <= lower;
7893

79-
bool more = Grow && (OnHold + OnFetch <= lower);
94+
if (Offset == Pages.size()) { // isn't processed yet
95+
SyncIndex(pageId);
96+
AddToQueue(head, pageId);
97+
}
8098

81-
return { Preload(head, 0).Touch(pageId, Stat), more, true };
99+
grow &= Index->IsValid() && Index->GetRowId() < EndRowId;
100+
101+
return {Pages.at(Offset).Touch(pageId, Stat), grow, true};
82102
}
83103

84104
void Forward(IPageLoadingQueue *head, ui64 upper) noexcept override
85105
{
86-
Preload(head, upper);
106+
Y_ABORT_UNLESS(Started, "Couldn't be called before Handle returns grow");
107+
108+
while (OnHold + OnFetch < upper && Index->IsValid() && Index->GetRowId() < EndRowId) {
109+
AddToQueue(head, Index->GetPageId());
110+
Y_ABORT_UNLESS(Index->Next() != EReady::Page);
111+
}
87112
}
88113

89114
void Apply(TArrayRef<NPageCollection::TLoadedPage> loaded) noexcept override
@@ -105,7 +130,7 @@ namespace NFwd {
105130

106131
Stat.Saved += one.Data.size();
107132
OnFetch -= one.Data.size();
108-
OnHold += it->Settle(one);
133+
OnHold += it->Settle(one); // settle of a dropped page returns 0 and releases its data
109134

110135
++it;
111136
}
@@ -114,65 +139,72 @@ namespace NFwd {
114139
}
115140

116141
private:
117-
TPage& Preload(IPageLoadingQueue *head, ui64 upper) noexcept
142+
void DropPagesBefore(TPageId pageId) noexcept
118143
{
119-
auto until = [this, upper]() {
120-
return OnHold + OnFetch < upper ? Max<TPageId>() : 0;
121-
};
144+
while (Offset < Pages.size()) {
145+
auto &page = Pages.at(Offset);
122146

123-
while (auto more = Index.More(until())) {
124-
auto size = head->AddToQueue(more, EPage::DataPage);
147+
if (page.PageId >= pageId) {
148+
break;
149+
}
125150

126-
Stat.Fetch += size;
127-
OnFetch += size;
151+
if (page.Size == 0) {
152+
Y_ABORT("Dropping page that has not been touched");
153+
} else if (page.Usage == EUsage::Keep && page) {
154+
OnHold -= Trace.Emplace(page);
155+
} else {
156+
OnHold -= page.Release().size();
157+
*(page.Ready() ? &Stat.After : &Stat.Before) += page.Size;
158+
}
128159

129-
Pages.emplace_back(more, size, 0, Max<TPageId>());
130-
Pages.back().Fetch = EFetch::Wait;
160+
// keep pending pages but increment offset
161+
Offset++;
131162
}
132-
133-
Grow = Grow && Index.On(true) < Max<TPageId>();
134-
135-
return Pages.at(Offset);
136163
}
137164

138-
TCache& Rewind(TPageId pageId) noexcept
165+
void Shrink() noexcept
139166
{
140-
while (auto drop = Index.Clean(pageId)) {
141-
auto &page = Pages.at(Offset);
142-
143-
if (!Pages || page.PageId != drop.PageId) {
144-
Y_ABORT("Dropping page that is not exist in cache");
145-
} else if (page.Size == 0) {
146-
Y_ABORT("Dropping page that has not been touched");
147-
} else if (page.Usage == EUsage::Keep) {
148-
OnHold -= Trace.Emplace(page);
149-
} else if (auto size = page.Release().size()) {
150-
OnHold -= size;
167+
for (; Offset && Pages[0].Ready(); Offset--) {
168+
Pages.pop_front();
169+
}
170+
}
151171

152-
*(page.Ready() ? &Stat.After : &Stat.Before) += size;
153-
}
172+
void SyncIndex(TPageId pageId) noexcept
173+
{
174+
if (!Started) {
175+
Y_ABORT_UNLESS(Index->Seek(BeginRowId) == EReady::Data);
176+
Y_ABORT_UNLESS(Index->GetPageId() <= pageId, "Requested page is out of slice bounds");
177+
Started = true;
178+
}
154179

155-
Offset++;
180+
while (Index->IsValid() && Index->GetPageId() < pageId) {
181+
Y_ABORT_UNLESS(Index->Next() == EReady::Data);
182+
Y_ABORT_UNLESS(Index->GetRowId() < EndRowId, "Requested page is out of slice bounds");
156183
}
157184

158-
return *this;
185+
Y_ABORT_UNLESS(Index->GetPageId() == pageId, "Requested page doesn't belong to the part");
186+
Y_ABORT_UNLESS(Index->Next() != EReady::Page);
159187
}
160188

161-
TCache& Shrink() noexcept
189+
void AddToQueue(IPageLoadingQueue *head, TPageId pageId) noexcept
162190
{
163-
for (; Offset && Pages[0].Ready(); Offset--)
164-
Pages.pop_front();
191+
auto size = head->AddToQueue(pageId, EPage::DataPage);
192+
193+
Stat.Fetch += size;
194+
OnFetch += size;
165195

166-
return *this;
196+
Y_ABORT_UNLESS(!Pages || Pages.back().PageId < pageId);
197+
Pages.emplace_back(pageId, size, 0, Max<TPageId>());
198+
Pages.back().Fetch = EFetch::Wait;
167199
}
168200

169201
private:
170-
bool Grow = true; /* Have some pages for Forward(...) */
171-
TForward Index;
172-
TRound<TPart::Trace> Trace;
202+
THolder<IIndexIter> Index; /* Points on next to load page */
203+
bool Started = false;
204+
TRowId BeginRowId, EndRowId;
205+
TLoadedPagesCircularBuffer<TPart::Trace> Trace;
173206

174207
/*_ Forward cache line state */
175-
176208
ui64 OnHold = 0;
177209
ui64 OnFetch = 0;
178210
ui32 Offset = 0;

ydb/core/tablet_flat/flat_fwd_env.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@
1010
#include "flat_table_subset.h"
1111
#include "flat_part_iface.h"
1212
#include "flat_part_store.h"
13-
#include "flat_sausage_packet.h"
1413
#include "flat_sausage_fetch.h"
1514
#include "util_fmt_abort.h"
16-
#include "util_basics.h"
1715
#include <util/generic/deque.h>
1816
#include <util/random/random.h>
1917
#include <util/generic/intrlist.h>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include "flat_fwd_misc.h"
2+
3+
Y_DECLARE_OUT_SPEC(, NKikimr::NTable::NFwd::TStat, stream, value) {
4+
value.Describe(stream);
5+
}

ydb/core/tablet_flat/flat_fwd_misc.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ namespace NFwd {
1818
{
1919
out
2020
<< "TFwd{"
21-
<< Fetch << "b"
22-
<< " > " << Saved << "b"
23-
<< " > " << Usage << "b"
24-
<< " +" << After << "b"
25-
<< " ~" << Before << "b"
21+
<< "fetch=" << Fetch
22+
<< ",saved=" << Saved
23+
<< ",usage=" << Usage
24+
<< ",after=" << After
25+
<< ",before=" << Before
2626
<< "}";
2727
}
2828

@@ -37,6 +37,8 @@ namespace NFwd {
3737
return *this;
3838
}
3939

40+
auto operator<=>(const TStat&) const = default;
41+
4042
ui64 Fetch = 0; /* Requested to load by cache */
4143
ui64 Saved = 0; /* Obtained by cache with DoSave() */
4244
ui64 Usage = 0; /* Actually was used by client */

ydb/core/tablet_flat/flat_fwd_page.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ namespace NFwd {
7575
const TSharedData* Touch(TPageId pageId, TStat &stat) noexcept
7676
{
7777
if (PageId != pageId || (!Data && Fetch == EFetch::Done)) {
78-
Y_ABORT("Touching page thatd doesn't fits to this action");
78+
Y_ABORT("Touching page that doesn't fit to this action");
7979
} else {
8080
auto to = Fetch == EFetch::None ? EUsage::Seen : EUsage::Keep;
8181

ydb/core/tablet_flat/flat_page_other.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ namespace NPage {
2828
Tags.resize(TagsCount + (TagsCount & 1), 0);
2929
Cook.reserve(tags);
3030

31-
Y_ABORT_UNLESS(tags <= ui32(-Min<i16>()), "Too many columnt tags");
31+
Y_ABORT_UNLESS(tags <= ui32(-Min<i16>()), "Too many column tags");
3232
}
3333

3434
void Put(TRowId row, ui16 tag, ui32 bytes) noexcept

0 commit comments

Comments
 (0)