Skip to content

Commit 6853d24

Browse files
authored
optimized SST index for blobs (index and iterator part) (#16992)
1 parent a55bf5d commit 6853d24

File tree

10 files changed

+389
-92
lines changed

10 files changed

+389
-92
lines changed

ydb/core/blobstorage/vdisk/hulldb/generic/blobstorage_hullwritesst.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,8 @@ namespace NKikimr {
412412
static_assert((SuffixSize >> 2 << 2) == SuffixSize, "expect (SuffixSize >> 2 << 2) == SuffixSize");
413413
static_assert(sizeof(TIdxDiskLinker) <= sizeof(TIdxDiskPlaceHolder), "expect sizeof(TIdxDiskLinker) <= sizeof(TIdxDiskPlaceHolder)");
414414

415+
typedef TRecIndex<TKey, TMemRec>::TRec TRec;
416+
415417
public:
416418
TIndexBuilder(TVDiskContextPtr vctx, EWriterDataType type, ui8 owner, ui64 ownerRound, ui32 chunkSize,
417419
ui32 appendBlockSize, ui32 writeBlockSize, ui64 sstId, bool createdByRepl,

ydb/core/blobstorage/vdisk/hulldb/generic/hullds_sst.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace NKikimr {
88
template <class TKey, class TMemRec>
99
void TLevelSegment<TKey, TMemRec>::OutputHtml(ui32 &index, ui32 level, IOutputStream &str, TIdxDiskPlaceHolder::TInfo &sum) const {
1010
HTML(str) {
11-
if (IsLoaded()) {
11+
if (this->IsLoaded()) {
1212
TABLER() {
1313
TABLED() {SMALL() {str << index;}}
1414
TABLED() {SMALL() {str << level;}}
@@ -31,7 +31,7 @@ namespace NKikimr {
3131

3232
template <class TKey, class TMemRec>
3333
void TLevelSegment<TKey, TMemRec>::OutputProto(ui32 level, google::protobuf::RepeatedPtrField<NKikimrVDisk::LevelStat> *rows) const {
34-
if (IsLoaded()) {
34+
if (this->IsLoaded()) {
3535
NKikimrVDisk::LevelStat *row = rows->Add();
3636
row->set_level(level);
3737
row->set_first_lsn(Info.FirstLsn);

ydb/core/blobstorage/vdisk/hulldb/generic/hullds_sst.h

Lines changed: 211 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,211 @@
1111

1212
namespace NKikimr {
1313

14+
template <class TKey, class TMemRec>
15+
struct TRecIndex : public TThrRefBase {
16+
#pragma pack(push, 4)
17+
struct TRec {
18+
TKey Key;
19+
TMemRec MemRec;
20+
21+
TRec() = default;
22+
23+
TRec(const TKey &key)
24+
: Key(key)
25+
, MemRec()
26+
{}
27+
28+
TRec(const TKey &key, const TMemRec &memRec)
29+
: Key(key)
30+
, MemRec(memRec)
31+
{}
32+
33+
struct TLess {
34+
bool operator ()(const TRec &x, const TKey &key) const {
35+
return x.Key < key;
36+
}
37+
};
38+
};
39+
#pragma pack(pop)
40+
41+
TTrackableVector<TRec> LoadedIndex;
42+
43+
TRecIndex(TVDiskContextPtr vctx)
44+
: LoadedIndex(TMemoryConsumer(vctx->SstIndex))
45+
{}
46+
47+
bool IsLoaded() const {
48+
return !LoadedIndex.empty();
49+
}
50+
51+
ui64 Elements() const {
52+
Y_DEBUG_ABORT_UNLESS(IsLoaded());
53+
return LoadedIndex.size();
54+
}
55+
};
56+
57+
template <>
58+
struct TRecIndex<TKeyLogoBlob, TMemRecLogoBlob> : public TThrRefBase {
59+
60+
// TODO: remove
61+
#pragma pack(push, 4)
62+
struct TRec {
63+
TKeyLogoBlob Key;
64+
TMemRecLogoBlob MemRec;
65+
66+
TRec() = default;
67+
68+
TRec(const TKeyLogoBlob &key)
69+
: Key(key)
70+
, MemRec()
71+
{}
72+
73+
TRec(const TKeyLogoBlob &key, const TMemRecLogoBlob &memRec)
74+
: Key(key)
75+
, MemRec(memRec)
76+
{}
77+
78+
struct TLess {
79+
bool operator ()(const TRec &x, const TKeyLogoBlob &key) const {
80+
return x.Key < key;
81+
}
82+
};
83+
};
84+
#pragma pack(pop)
85+
86+
#pragma pack(push, 4)
87+
struct TLogoBlobIdHigh {
88+
union {
89+
struct {
90+
ui64 TabletId; // 8 bytes
91+
ui64 StepR1 : 24; // 8 bytes
92+
ui64 Generation : 32;
93+
ui64 Channel : 8;
94+
} N;
95+
96+
ui64 X[2];
97+
} Raw;
98+
99+
explicit TLogoBlobIdHigh(const TLogoBlobID& id) {
100+
Raw.X[0] = id.GetRaw()[0];
101+
Raw.X[1] = id.GetRaw()[1];
102+
}
103+
104+
TLogoBlobIdHigh(ui64 tabletId, ui32 generation, ui32 step, ui8 channel) {
105+
Raw.N.TabletId = tabletId;
106+
Raw.N.Channel = channel;
107+
Raw.N.Generation = generation;
108+
Raw.N.StepR1 = (step & 0xFFFFFF00ull) >> 8;
109+
}
110+
111+
bool operator == (const TLogoBlobIdHigh& r) const {
112+
return Raw.X[0] == r.Raw.X[0] && Raw.X[1] == r.Raw.X[1];
113+
}
114+
115+
bool operator != (const TLogoBlobIdHigh& r) const {
116+
return !(operator == (r));
117+
}
118+
119+
bool operator < (const TLogoBlobIdHigh& r) const {
120+
return Raw.X[0] != r.Raw.X[0] ? Raw.X[0] < r.Raw.X[0] : Raw.X[1] < r.Raw.X[1];
121+
}
122+
};
123+
124+
static_assert(sizeof(TLogoBlobIdHigh) == 16, "expect sizeof(TLogoBlobIdHigh) == 16");
125+
126+
struct TLogoBlobIdLow {
127+
union {
128+
struct {
129+
ui64 PartId : 4; // 8 bytes
130+
ui64 BlobSize : 26;
131+
ui64 CrcMode : 2;
132+
ui64 Cookie : 24;
133+
ui64 StepR2 : 8;
134+
} N;
135+
136+
ui64 X;
137+
} Raw;
138+
139+
explicit TLogoBlobIdLow(const TLogoBlobID& id) {
140+
Raw.X = id.GetRaw()[2];
141+
}
142+
143+
TLogoBlobIdLow(ui32 step, ui32 cookie, ui32 crcMode, ui32 blobSize, ui32 partId) {
144+
Raw.N.StepR2 = step & 0x000000FFull;
145+
Raw.N.Cookie = cookie;
146+
Raw.N.CrcMode = crcMode;
147+
Raw.N.BlobSize = blobSize;
148+
Raw.N.PartId = partId;
149+
}
150+
151+
bool operator == (const TLogoBlobIdLow& r) const {
152+
return Raw.X == r.Raw.X;
153+
}
154+
155+
bool operator != (const TLogoBlobIdLow& r) const {
156+
return !(operator == (r));
157+
}
158+
159+
bool operator < (const TLogoBlobIdLow& r) const {
160+
return Raw.X < r.Raw.X;
161+
}
162+
};
163+
164+
static_assert(sizeof(TLogoBlobIdLow) == 8, "expect sizeof(TLogoBlobIdLow) == 8");
165+
166+
struct TRecHigh {
167+
TLogoBlobIdHigh Key;
168+
ui32 LowRangeEndIndex;
169+
170+
struct TLess {
171+
bool operator ()(const TRecHigh& l, const TLogoBlobIdHigh& r) const {
172+
return l.Key < r;
173+
}
174+
};
175+
};
176+
177+
static_assert(sizeof(TRecHigh) == 20, "expect sizeof(TRecHigh) == 20");
178+
179+
struct TRecLow {
180+
TLogoBlobIdLow Key;
181+
TMemRecLogoBlob MemRec;
182+
183+
struct TLess {
184+
bool operator ()(const TRecLow& l, const TLogoBlobIdLow& r) const {
185+
return l.Key < r;
186+
}
187+
};
188+
};
189+
190+
static_assert(sizeof(TRecLow) == 28, "expect sizeof(TRecLow) == 28");
191+
#pragma pack(pop)
192+
193+
TTrackableVector<TRecHigh> IndexHigh;
194+
TTrackableVector<TRecLow> IndexLow;
195+
196+
TTrackableVector<TRec> LoadedIndex; // TODO: remove
197+
198+
TRecIndex(TVDiskContextPtr vctx)
199+
: IndexHigh(TMemoryConsumer(vctx->SstIndex))
200+
, IndexLow(TMemoryConsumer(vctx->SstIndex))
201+
, LoadedIndex(TMemoryConsumer(vctx->SstIndex))
202+
{}
203+
204+
bool IsLoaded() const {
205+
return !LoadedIndex.empty();
206+
}
207+
208+
ui64 Elements() const {
209+
Y_DEBUG_ABORT_UNLESS(IsLoaded());
210+
return LoadedIndex.size();
211+
}
212+
};
213+
14214
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
15215
// TLevelSegment
16216
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17217
template <class TKey, class TMemRec>
18-
struct TLevelSegment : public TThrRefBase {
218+
struct TLevelSegment : public TRecIndex<TKey, TMemRec> {
19219
typedef TLevelSegment<TKey, TMemRec> TThis;
20220
using TKeyType = TKey;
21221
using TMemRecType = TMemRec;
@@ -56,34 +256,7 @@ namespace NKikimr {
56256
}
57257
};
58258

59-
// records stored in the index
60-
#pragma pack(push, 4)
61-
struct TRec {
62-
TKey Key;
63-
TMemRec MemRec;
64-
65-
TRec() = default;
66-
67-
TRec(const TKey &key)
68-
: Key(key)
69-
, MemRec()
70-
{}
71-
72-
TRec(const TKey &key, const TMemRec &memRec)
73-
: Key(key)
74-
, MemRec(memRec)
75-
{}
76-
77-
struct TLess {
78-
bool operator () (const TRec &x, const TKey &key) const {
79-
return x.Key < key;
80-
}
81-
};
82-
};
83-
#pragma pack(pop)
84-
85259
TDiskPart LastPartAddr; // tail of reverted list of parts (on disk)
86-
TTrackableVector<TRec> LoadedIndex; // the whole index loaded into memory
87260
TTrackableVector<TDiskPart> LoadedOutbound;
88261
TIdxDiskPlaceHolder::TInfo Info;
89262
TVector<ui32> AllChunks; // all chunk ids that store index and data for this segment
@@ -95,17 +268,17 @@ namespace NKikimr {
95268
ui64 VolatileOrderId = 0;
96269

97270
TLevelSegment(TVDiskContextPtr vctx)
98-
: LastPartAddr()
99-
, LoadedIndex(TMemoryConsumer(vctx->SstIndex))
271+
: TRecIndex<TKey, TMemRec>(vctx)
272+
, LastPartAddr()
100273
, LoadedOutbound(TMemoryConsumer(vctx->SstIndex))
101274
, Info()
102275
, AllChunks()
103276
, StorageRatio()
104277
{}
105278

106279
TLevelSegment(TVDiskContextPtr vctx, const TDiskPart &addr)
107-
: LastPartAddr(addr)
108-
, LoadedIndex(TMemoryConsumer(vctx->SstIndex))
280+
: TRecIndex<TKey, TMemRec>(vctx)
281+
, LastPartAddr(addr)
109282
, LoadedOutbound(TMemoryConsumer(vctx->SstIndex))
110283
, Info()
111284
, AllChunks()
@@ -115,8 +288,8 @@ namespace NKikimr {
115288
}
116289

117290
TLevelSegment(TVDiskContextPtr vctx, const NKikimrVDiskData::TDiskPart &pb)
118-
: LastPartAddr(pb)
119-
, LoadedIndex(TMemoryConsumer(vctx->SstIndex))
291+
: TRecIndex<TKey, TMemRec>(vctx)
292+
, LastPartAddr(pb)
120293
, LoadedOutbound(TMemoryConsumer(vctx->SstIndex))
121294
, Info()
122295
, AllChunks()
@@ -127,10 +300,6 @@ namespace NKikimr {
127300
return LastPartAddr;
128301
}
129302

130-
bool IsLoaded() const {
131-
return !LoadedIndex.empty();
132-
}
133-
134303
void SetAddr(const TDiskPart &addr) {
135304
LastPartAddr = addr;
136305
}
@@ -163,7 +332,7 @@ namespace NKikimr {
163332
TMemIterator it(this);
164333
it.SeekToFirst();
165334
while (it.Valid()) {
166-
const TMemRec& memRec = it->MemRec;
335+
const TMemRec& memRec = it.GetMemRec();
167336
switch (memRec.GetType()) {
168337
case TBlobType::HugeBlob:
169338
case TBlobType::ManyHugeBlobs:
@@ -189,13 +358,9 @@ namespace NKikimr {
189358

190359
ui64 GetFirstLsn() const { return Info.FirstLsn; }
191360
ui64 GetLastLsn() const { return Info.LastLsn; }
192-
const TKey &FirstKey() const;
193-
const TKey &LastKey() const;
194-
// number of elements in the sst
195-
ui64 Elements() const {
196-
Y_DEBUG_ABORT_UNLESS(IsLoaded());
197-
return LoadedIndex.size();
198-
}
361+
TKey FirstKey() const;
362+
TKey LastKey() const;
363+
199364
// append cur seg chunk ids (index and data) to the vector
200365
void FillInChunkIds(TVector<ui32> &vec) const {
201366
// copy chunks ids
@@ -218,9 +383,7 @@ namespace NKikimr {
218383
class TWriter;
219384
};
220385

221-
extern template struct TLevelSegment<TKeyLogoBlob, TMemRecLogoBlob>;
222386
extern template struct TLevelSegment<TKeyBarrier, TMemRecBarrier>;
223387
extern template struct TLevelSegment<TKeyBlock, TMemRecBlock>;
224388

225389
} // NKikimr
226-

0 commit comments

Comments
 (0)