Skip to content

Commit aa2486b

Browse files
pdillingerfacebook-github-bot
authored andcommitted
Refactor some confusing logic in PlainTableReader
Summary: Pull Request resolved: facebook#5780 Test Plan: existing plain table unit test Differential Revision: D17368629 Pulled By: pdillinger fbshipit-source-id: f25409cdc2f39ebe8d5cbb599cf820270e6b5d26
1 parent 1a928c2 commit aa2486b

File tree

12 files changed

+295
-215
lines changed

12 files changed

+295
-215
lines changed

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,11 @@ ifeq ($(USE_FOLLY_DISTRIBUTED_MUTEX),1)
332332
endif
333333
endif
334334

335+
ifdef TEST_CACHE_LINE_SIZE
336+
PLATFORM_CCFLAGS += -DTEST_CACHE_LINE_SIZE=$(TEST_CACHE_LINE_SIZE)
337+
PLATFORM_CXXFLAGS += -DTEST_CACHE_LINE_SIZE=$(TEST_CACHE_LINE_SIZE)
338+
endif
339+
335340
# This (the first rule) must depend on "all".
336341
default: all
337342

db/db_properties_test.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,8 @@ void VerifySimilar(uint64_t a, uint64_t b, double bias) {
212212

213213
void VerifyTableProperties(const TableProperties& base_tp,
214214
const TableProperties& new_tp,
215-
double filter_size_bias = 0.1,
215+
double filter_size_bias =
216+
CACHE_LINE_SIZE >= 256 ? 0.15 : 0.1,
216217
double index_size_bias = 0.1,
217218
double data_size_bias = 0.1,
218219
double num_data_blocks_bias = 0.05) {
@@ -266,7 +267,8 @@ void GetExpectedTableProperties(
266267
// discount 1 byte as value size is not encoded in value delta encoding
267268
(value_delta_encoding ? 1 : 0));
268269
expected_tp->filter_size =
269-
kTableCount * (kKeysPerTable * kBloomBitsPerKey / 8);
270+
kTableCount * ((kKeysPerTable * kBloomBitsPerKey + 7) / 8 +
271+
/*average-ish overhead*/ CACHE_LINE_SIZE / 2);
270272
}
271273
} // anonymous namespace
272274

port/port_posix.h

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -178,22 +178,31 @@ typedef pthread_once_t OnceType;
178178
extern void InitOnce(OnceType* once, void (*initializer)());
179179

180180
#ifndef CACHE_LINE_SIZE
181-
#if defined(__s390__)
182-
#define CACHE_LINE_SIZE 256U
183-
#elif defined(__powerpc__) || defined(__aarch64__)
184-
#define CACHE_LINE_SIZE 128U
181+
// To test behavior with non-native cache line size, e.g. for
182+
// Bloom filters, set TEST_CACHE_LINE_SIZE to the desired test size.
183+
// This disables ALIGN_AS to keep it from failing compilation.
184+
#ifdef TEST_CACHE_LINE_SIZE
185+
#define CACHE_LINE_SIZE TEST_CACHE_LINE_SIZE
186+
#define ALIGN_AS(n) /*empty*/
185187
#else
186-
#define CACHE_LINE_SIZE 64U
188+
#if defined(__s390__)
189+
#define CACHE_LINE_SIZE 256U
190+
#elif defined(__powerpc__) || defined(__aarch64__)
191+
#define CACHE_LINE_SIZE 128U
192+
#else
193+
#define CACHE_LINE_SIZE 64U
194+
#endif
195+
#define ALIGN_AS(n) alignas(n)
187196
#endif
188197
#endif
189198

199+
static_assert((CACHE_LINE_SIZE & (CACHE_LINE_SIZE - 1)) == 0,
200+
"Cache line size must be a power of 2 number of bytes");
190201

191202
extern void *cacheline_aligned_alloc(size_t size);
192203

193204
extern void cacheline_aligned_free(void *memblock);
194205

195-
#define ALIGN_AS(n) alignas(n)
196-
197206
#define PREFETCH(addr, rw, locality) __builtin_prefetch(addr, rw, locality)
198207

199208
extern void Crash(const std::string& srcfile, int srcline);

table/full_filter_bits_builder.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ class Slice;
2020

2121
class FullFilterBitsBuilder : public FilterBitsBuilder {
2222
public:
23-
explicit FullFilterBitsBuilder(const size_t bits_per_key,
24-
const size_t num_probes);
23+
explicit FullFilterBitsBuilder(const int bits_per_key,
24+
const int num_probes);
2525

2626
// No Copy allowed
2727
FullFilterBitsBuilder(const FullFilterBitsBuilder&) = delete;
@@ -56,8 +56,8 @@ class FullFilterBitsBuilder : public FilterBitsBuilder {
5656

5757
private:
5858
friend class FullFilterBlockTest_DuplicateEntries_Test;
59-
size_t bits_per_key_;
60-
size_t num_probes_;
59+
int bits_per_key_;
60+
int num_probes_;
6161
std::vector<uint32_t> hash_entries_;
6262

6363
// Get totalbits that optimized for cpu cache line

table/plain/plain_table_bloom.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ uint32_t GetTotalBitsForLocality(uint32_t total_bits) {
3333
PlainTableBloomV1::PlainTableBloomV1(uint32_t num_probes)
3434
: kTotalBits(0), kNumBlocks(0), kNumProbes(num_probes), data_(nullptr) {}
3535

36-
void PlainTableBloomV1::SetRawData(unsigned char* raw_data, uint32_t total_bits,
36+
void PlainTableBloomV1::SetRawData(char* raw_data, uint32_t total_bits,
3737
uint32_t num_blocks) {
38-
data_ = reinterpret_cast<uint8_t*>(raw_data);
38+
data_ = raw_data;
3939
kTotalBits = total_bits;
4040
kNumBlocks = num_blocks;
4141
}
@@ -63,7 +63,7 @@ void PlainTableBloomV1::SetTotalBits(Allocator* allocator,
6363
if (kNumBlocks > 0 && cache_line_offset > 0) {
6464
raw += CACHE_LINE_SIZE - cache_line_offset;
6565
}
66-
data_ = reinterpret_cast<uint8_t*>(raw);
66+
data_ = raw;
6767
}
6868

6969
void BloomBlockBuilder::AddKeysHashes(const std::vector<uint32_t>& keys_hashes) {

table/plain/plain_table_bloom.h

Lines changed: 19 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@
1010
#include "rocksdb/slice.h"
1111

1212
#include "port/port.h"
13+
#include "util/bloom_impl.h"
1314
#include "util/hash.h"
1415

16+
#include "third-party/folly/folly/ConstexprMath.h"
17+
1518
#include <memory>
1619

1720
namespace rocksdb {
@@ -51,10 +54,10 @@ class PlainTableBloomV1 {
5154
uint32_t GetNumBlocks() const { return kNumBlocks; }
5255

5356
Slice GetRawData() const {
54-
return Slice(reinterpret_cast<char*>(data_), GetTotalBits() / 8);
57+
return Slice(data_, GetTotalBits() / 8);
5558
}
5659

57-
void SetRawData(unsigned char* raw_data, uint32_t total_bits,
60+
void SetRawData(char* raw_data, uint32_t total_bits,
5861
uint32_t num_blocks = 0);
5962

6063
uint32_t GetTotalBits() const { return kTotalBits; }
@@ -66,7 +69,10 @@ class PlainTableBloomV1 {
6669
uint32_t kNumBlocks;
6770
const uint32_t kNumProbes;
6871

69-
uint8_t* data_;
72+
char* data_;
73+
74+
static constexpr int LOG2_CACHE_LINE_SIZE =
75+
folly::constexpr_log2(CACHE_LINE_SIZE);
7076
};
7177

7278
#if defined(_MSC_VER)
@@ -76,8 +82,9 @@ class PlainTableBloomV1 {
7682
#endif
7783
inline void PlainTableBloomV1::Prefetch(uint32_t h) {
7884
if (kNumBlocks != 0) {
79-
uint32_t b = ((h >> 11 | (h << 21)) % kNumBlocks) * (CACHE_LINE_SIZE * 8);
80-
PREFETCH(&(data_[b / 8]), 0, 3);
85+
uint32_t ignored;
86+
LegacyLocalityBloomImpl</*ExtraRotates*/true>::PrepareHashMayMatch(
87+
h, kNumBlocks, data_, &ignored, LOG2_CACHE_LINE_SIZE);
8188
}
8289
}
8390
#if defined(_MSC_VER)
@@ -86,54 +93,22 @@ inline void PlainTableBloomV1::Prefetch(uint32_t h) {
8693

8794
inline bool PlainTableBloomV1::MayContainHash(uint32_t h) const {
8895
assert(IsInitialized());
89-
const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits
9096
if (kNumBlocks != 0) {
91-
uint32_t b = ((h >> 11 | (h << 21)) % kNumBlocks) * (CACHE_LINE_SIZE * 8);
92-
for (uint32_t i = 0; i < kNumProbes; ++i) {
93-
// Since CACHE_LINE_SIZE is defined as 2^n, this line will be optimized
94-
// to a simple and operation by compiler.
95-
const uint32_t bitpos = b + (h % (CACHE_LINE_SIZE * 8));
96-
if ((data_[bitpos / 8] & (1 << (bitpos % 8))) == 0) {
97-
return false;
98-
}
99-
// Rotate h so that we don't reuse the same bytes.
100-
h = h / (CACHE_LINE_SIZE * 8) +
101-
(h % (CACHE_LINE_SIZE * 8)) * (0x20000000U / CACHE_LINE_SIZE);
102-
h += delta;
103-
}
97+
return LegacyLocalityBloomImpl<true>::HashMayMatch(
98+
h, kNumBlocks, kNumProbes, data_, LOG2_CACHE_LINE_SIZE);
10499
} else {
105-
for (uint32_t i = 0; i < kNumProbes; ++i) {
106-
const uint32_t bitpos = h % kTotalBits;
107-
if ((data_[bitpos / 8] & (1 << (bitpos % 8))) == 0) {
108-
return false;
109-
}
110-
h += delta;
111-
}
100+
return LegacyNoLocalityBloomImpl::HashMayMatch(
101+
h, kTotalBits, kNumProbes, data_);
112102
}
113-
return true;
114103
}
115104

116105
inline void PlainTableBloomV1::AddHash(uint32_t h) {
117106
assert(IsInitialized());
118-
const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits
119107
if (kNumBlocks != 0) {
120-
uint32_t b = ((h >> 11 | (h << 21)) % kNumBlocks) * (CACHE_LINE_SIZE * 8);
121-
for (uint32_t i = 0; i < kNumProbes; ++i) {
122-
// Since CACHE_LINE_SIZE is defined as 2^n, this line will be optimized
123-
// to a simple and operation by compiler.
124-
const uint32_t bitpos = b + (h % (CACHE_LINE_SIZE * 8));
125-
data_[bitpos / 8] |= (1 << (bitpos % 8));
126-
// Rotate h so that we don't reuse the same bytes.
127-
h = h / (CACHE_LINE_SIZE * 8) +
128-
(h % (CACHE_LINE_SIZE * 8)) * (0x20000000U / CACHE_LINE_SIZE);
129-
h += delta;
130-
}
108+
LegacyLocalityBloomImpl<true>::AddHash(
109+
h, kNumBlocks, kNumProbes, data_, LOG2_CACHE_LINE_SIZE);
131110
} else {
132-
for (uint32_t i = 0; i < kNumProbes; ++i) {
133-
const uint32_t bitpos = h % kTotalBits;
134-
data_[bitpos / 8] |= (1 << (bitpos % 8));
135-
h += delta;
136-
}
111+
LegacyNoLocalityBloomImpl::AddHash(h, kTotalBits, kNumProbes, data_);
137112
}
138113
}
139114

table/plain/plain_table_reader.cc

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -260,23 +260,19 @@ Status PlainTableReader::PopulateIndexRecordList(
260260
return s;
261261
}
262262

263-
void PlainTableReader::AllocateAndFillBloom(
264-
int bloom_bits_per_key, int num_prefixes, size_t huge_page_tlb_size,
265-
std::vector<uint32_t>* prefix_hashes) {
266-
if (!IsTotalOrderMode()) {
267-
uint32_t bloom_total_bits = num_prefixes * bloom_bits_per_key;
268-
if (bloom_total_bits > 0) {
269-
enable_bloom_ = true;
270-
bloom_.SetTotalBits(&arena_, bloom_total_bits, ioptions_.bloom_locality,
271-
huge_page_tlb_size, ioptions_.info_log);
272-
FillBloom(prefix_hashes);
273-
}
263+
void PlainTableReader::AllocateBloom(int bloom_bits_per_key, int num_keys,
264+
size_t huge_page_tlb_size) {
265+
uint32_t bloom_total_bits = num_keys * bloom_bits_per_key;
266+
if (bloom_total_bits > 0) {
267+
enable_bloom_ = true;
268+
bloom_.SetTotalBits(&arena_, bloom_total_bits, ioptions_.bloom_locality,
269+
huge_page_tlb_size, ioptions_.info_log);
274270
}
275271
}
276272

277-
void PlainTableReader::FillBloom(std::vector<uint32_t>* prefix_hashes) {
273+
void PlainTableReader::FillBloom(const std::vector<uint32_t>& prefix_hashes) {
278274
assert(bloom_.IsInitialized());
279-
for (auto prefix_hash : *prefix_hashes) {
275+
for (const auto prefix_hash : prefix_hashes) {
280276
bloom_.AddHash(prefix_hash);
281277
}
282278
}
@@ -354,14 +350,9 @@ Status PlainTableReader::PopulateIndex(TableProperties* props,
354350
if (!index_in_file) {
355351
// Allocate bloom filter here for total order mode.
356352
if (IsTotalOrderMode()) {
357-
uint32_t num_bloom_bits =
358-
static_cast<uint32_t>(table_properties_->num_entries) *
359-
bloom_bits_per_key;
360-
if (num_bloom_bits > 0) {
361-
enable_bloom_ = true;
362-
bloom_.SetTotalBits(&arena_, num_bloom_bits, ioptions_.bloom_locality,
363-
huge_page_tlb_size, ioptions_.info_log);
364-
}
353+
AllocateBloom(bloom_bits_per_key,
354+
static_cast<uint32_t>(table_properties_->num_entries),
355+
huge_page_tlb_size);
365356
}
366357
} else if (bloom_in_file) {
367358
enable_bloom_ = true;
@@ -377,8 +368,7 @@ Status PlainTableReader::PopulateIndex(TableProperties* props,
377368
}
378369
// cast away const qualifier, because bloom_ won't be changed
379370
bloom_.SetRawData(
380-
const_cast<unsigned char*>(
381-
reinterpret_cast<const unsigned char*>(bloom_block->data())),
371+
const_cast<char*>(bloom_block->data()),
382372
static_cast<uint32_t>(bloom_block->size()) * 8, num_blocks);
383373
} else {
384374
// Index in file but no bloom in file. Disable bloom filter in this case.
@@ -392,6 +382,7 @@ Status PlainTableReader::PopulateIndex(TableProperties* props,
392382

393383
std::vector<uint32_t> prefix_hashes;
394384
if (!index_in_file) {
385+
// Populates _bloom if enabled (total order mode)
395386
s = PopulateIndexRecordList(&index_builder, &prefix_hashes);
396387
if (!s.ok()) {
397388
return s;
@@ -404,10 +395,15 @@ Status PlainTableReader::PopulateIndex(TableProperties* props,
404395
}
405396

406397
if (!index_in_file) {
407-
// Calculated bloom filter size and allocate memory for
408-
// bloom filter based on the number of prefixes, then fill it.
409-
AllocateAndFillBloom(bloom_bits_per_key, index_.GetNumPrefixes(),
410-
huge_page_tlb_size, &prefix_hashes);
398+
if (!IsTotalOrderMode()) {
399+
// Calculated bloom filter size and allocate memory for
400+
// bloom filter based on the number of prefixes, then fill it.
401+
AllocateBloom(bloom_bits_per_key, index_.GetNumPrefixes(),
402+
huge_page_tlb_size);
403+
if (enable_bloom_) {
404+
FillBloom(prefix_hashes);
405+
}
406+
}
411407
}
412408

413409
// Fill two table properties.

table/plain/plain_table_reader.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,12 +209,11 @@ class PlainTableReader: public TableReader {
209209
Status PopulateIndexRecordList(PlainTableIndexBuilder* index_builder,
210210
std::vector<uint32_t>* prefix_hashes);
211211

212-
// Internal helper function to allocate memory for bloom filter and fill it
213-
void AllocateAndFillBloom(int bloom_bits_per_key, int num_prefixes,
214-
size_t huge_page_tlb_size,
215-
std::vector<uint32_t>* prefix_hashes);
212+
// Internal helper function to allocate memory for bloom filter
213+
void AllocateBloom(int bloom_bits_per_key, int num_prefixes,
214+
size_t huge_page_tlb_size);
216215

217-
void FillBloom(std::vector<uint32_t>* prefix_hashes);
216+
void FillBloom(const std::vector<uint32_t>& prefix_hashes);
218217

219218
// Read the key and value at `offset` to parameters for keys, the and
220219
// `seekable`.

third-party/folly/folly/ConstexprMath.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,32 @@ template <typename T, typename... Ts>
1414
constexpr T constexpr_max(T a, T b, Ts... ts) {
1515
return b < a ? constexpr_max(a, ts...) : constexpr_max(b, ts...);
1616
}
17+
18+
namespace detail {
19+
template <typename T>
20+
constexpr T constexpr_log2_(T a, T e) {
21+
return e == T(1) ? a : constexpr_log2_(a + T(1), e / T(2));
22+
}
23+
24+
template <typename T>
25+
constexpr T constexpr_log2_ceil_(T l2, T t) {
26+
return l2 + T(T(1) << l2 < t ? 1 : 0);
27+
}
28+
29+
template <typename T>
30+
constexpr T constexpr_square_(T t) {
31+
return t * t;
32+
}
33+
} // namespace detail
34+
35+
template <typename T>
36+
constexpr T constexpr_log2(T t) {
37+
return detail::constexpr_log2_(T(0), t);
38+
}
39+
40+
template <typename T>
41+
constexpr T constexpr_log2_ceil(T t) {
42+
return detail::constexpr_log2_ceil_(constexpr_log2(t), t);
43+
}
44+
1745
} // namespace folly

0 commit comments

Comments
 (0)