Branch data Line data Source code
1 : : // Copyright (c) 2012 The LevelDB Authors. All rights reserved.
2 : : // Use of this source code is governed by a BSD-style license that can be
3 : : // found in the LICENSE file. See the AUTHORS file for names of contributors.
4 : :
5 : : #include "leveldb/filter_policy.h"
6 : :
7 : : #include "leveldb/slice.h"
8 : : #include "util/hash.h"
9 : :
10 : : namespace leveldb {
11 : :
12 : : namespace {
13 : 1320586 : static uint32_t BloomHash(const Slice& key) {
14 : 1320586 : return Hash(key.data(), key.size(), 0xbc9f1d34);
15 : : }
16 : :
17 : : class BloomFilterPolicy : public FilterPolicy {
18 : : public:
19 [ - + ]: 489 : explicit BloomFilterPolicy(int bits_per_key) : bits_per_key_(bits_per_key) {
20 : : // We intentionally round down to reduce probing cost a little bit
21 : 489 : k_ = static_cast<size_t>(bits_per_key * 0.69); // 0.69 =~ ln(2)
22 [ - + ]: 489 : if (k_ < 1) k_ = 1;
23 [ - + ]: 489 : if (k_ > 30) k_ = 30;
24 : 489 : }
25 : :
26 : 228 : const char* Name() const override { return "leveldb.BuiltinBloomFilter2"; }
27 : :
28 : 418 : void CreateFilter(const Slice* keys, int n, std::string* dst) const override {
29 : : // Compute bloom filter size (in both bits and bytes)
30 : 418 : size_t bits = n * bits_per_key_;
31 : :
32 : : // For small n, we can see a very high false positive rate. Fix it
33 : : // by enforcing a minimum bloom filter length.
34 [ + + ]: 418 : if (bits < 64) bits = 64;
35 : :
36 : 418 : size_t bytes = (bits + 7) / 8;
37 : 418 : bits = bytes * 8;
38 : :
39 [ - + ]: 418 : const size_t init_size = dst->size();
40 : 418 : dst->resize(init_size + bytes, 0);
41 : 418 : dst->push_back(static_cast<char>(k_)); // Remember # of probes in filter
42 : 418 : char* array = &(*dst)[init_size];
43 [ + + ]: 28783 : for (int i = 0; i < n; i++) {
44 : : // Use double-hashing to generate a sequence of hash values.
45 : : // See analysis in [Kirsch,Mitzenmacher 2006].
46 : 28365 : uint32_t h = BloomHash(keys[i]);
47 : 28365 : const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits
48 [ + + ]: 198555 : for (size_t j = 0; j < k_; j++) {
49 : 170190 : const uint32_t bitpos = h % bits;
50 : 170190 : array[bitpos / 8] |= (1 << (bitpos % 8));
51 : 170190 : h += delta;
52 : : }
53 : : }
54 : 418 : }
55 : :
56 : 1292221 : bool KeyMayMatch(const Slice& key, const Slice& bloom_filter) const override {
57 [ + - ]: 1292221 : const size_t len = bloom_filter.size();
58 [ + - ]: 1292221 : if (len < 2) return false;
59 : :
60 [ + - ]: 1292221 : const char* array = bloom_filter.data();
61 : 1292221 : const size_t bits = (len - 1) * 8;
62 : :
63 : : // Use the encoded k so that we can read filters generated by
64 : : // bloom filters created using different parameters.
65 : 1292221 : const size_t k = array[len - 1];
66 [ + - ]: 1292221 : if (k > 30) {
67 : : // Reserved for potentially new encodings for short bloom filters.
68 : : // Consider it a match.
69 : : return true;
70 : : }
71 : :
72 : 1292221 : uint32_t h = BloomHash(key);
73 : 1292221 : const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits
74 [ + + ]: 1843664 : for (size_t j = 0; j < k; j++) {
75 : 1778842 : const uint32_t bitpos = h % bits;
76 [ + + ]: 1778842 : if ((array[bitpos / 8] & (1 << (bitpos % 8))) == 0) return false;
77 : 551443 : h += delta;
78 : : }
79 : : return true;
80 : : }
81 : :
82 : : private:
83 : : size_t bits_per_key_;
84 : : size_t k_;
85 : : };
86 : : } // namespace
87 : :
88 : 489 : const FilterPolicy* NewBloomFilterPolicy(int bits_per_key) {
89 : 489 : return new BloomFilterPolicy(bits_per_key);
90 : : }
91 : :
92 : : } // namespace leveldb
|