forked from linxGnu/grocksdb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfilter_policy.go
149 lines (131 loc) · 6.43 KB
/
filter_policy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package grocksdb
// #include "rocksdb/c.h"
import "C"
// FilterPolicy is a factory type that allows the RocksDB database to create a
// filter, such as a bloom filter, which will used to reduce reads.
type FilterPolicy interface {
// keys contains a list of keys (potentially with duplicates)
// that are ordered according to the user supplied comparator.
CreateFilter(keys [][]byte) []byte
// "filter" contains the data appended by a preceding call to
// CreateFilter(). This method must return true if
// the key was in the list of keys passed to CreateFilter().
// This method may return true or false if the key was not on the
// list, but it should aim to return false with a high probability.
KeyMayMatch(key []byte, filter []byte) bool
// Return the name of this policy.
Name() string
// Destroy filter policy object.
Destroy()
}
// NewNativeFilterPolicy creates a FilterPolicy object.
func NewNativeFilterPolicy(c *C.rocksdb_filterpolicy_t) FilterPolicy {
return nativeFilterPolicy{c}
}
type nativeFilterPolicy struct {
c *C.rocksdb_filterpolicy_t
}
func (fp nativeFilterPolicy) CreateFilter(keys [][]byte) []byte { return nil }
func (fp nativeFilterPolicy) KeyMayMatch(key []byte, filter []byte) bool { return false }
func (fp nativeFilterPolicy) Name() string { return "" }
func (fp nativeFilterPolicy) Destroy() {
C.rocksdb_filterpolicy_destroy(fp.c)
fp.c = nil
}
// NewBloomFilter returns a new filter policy that uses a bloom filter with approximately
// the specified number of bits per key. A good value for bits_per_key
// is 10, which yields a filter with ~1% false positive rate.
//
// Note: if you are using a custom comparator that ignores some parts
// of the keys being compared, you must not use NewBloomFilterPolicy()
// and must provide your own FilterPolicy that also ignores the
// corresponding parts of the keys. For example, if the comparator
// ignores trailing spaces, it would be incorrect to use a
// FilterPolicy (like NewBloomFilterPolicy) that does not ignore
// trailing spaces in keys.
func NewBloomFilter(bitsPerKey float64) FilterPolicy {
return NewNativeFilterPolicy(C.rocksdb_filterpolicy_create_bloom(C.double(bitsPerKey)))
}
// NewBloomFilterFull returns a new filter policy that uses a full bloom filter
// with approximately the specified number of bits per key. A good value for
// bits_per_key is 10, which yields a filter with ~1% false positive rate.
//
// Note: if you are using a custom comparator that ignores some parts
// of the keys being compared, you must not use NewBloomFilterPolicy()
// and must provide your own FilterPolicy that also ignores the
// corresponding parts of the keys. For example, if the comparator
// ignores trailing spaces, it would be incorrect to use a
// FilterPolicy (like NewBloomFilterPolicy) that does not ignore
// trailing spaces in keys.
func NewBloomFilterFull(bitsPerKey float64) FilterPolicy {
return NewNativeFilterPolicy(C.rocksdb_filterpolicy_create_bloom_full(C.double(bitsPerKey)))
}
// NewRibbonFilterPolicy creates a new Bloom alternative that saves about 30% space compared to
// Bloom filters, with similar query times but roughly 3-4x CPU time
// and 3x temporary space usage during construction. For example, if
// you pass in 10 for bloom_equivalent_bits_per_key, you'll get the same
// 0.95% FP rate as Bloom filter but only using about 7 bits per key.
//
// The space savings of Ribbon filters makes sense for lower (higher
// numbered; larger; longer-lived) levels of LSM, whereas the speed of
// Bloom filters make sense for highest levels of LSM. Setting
// bloom_before_level allows for this design with Level and Universal
// compaction styles. For example, bloom_before_level=1 means that Bloom
// filters will be used in level 0, including flushes, and Ribbon
// filters elsewhere, including FIFO compaction and external SST files.
// For this option, memtable flushes are considered level -1 (so that
// flushes can be distinguished from intra-L0 compaction).
// bloom_before_level=0 (default) -> Generate Bloom filters only for
// flushes under Level and Universal compaction styles.
// bloom_before_level=-1 -> Always generate Ribbon filters (except in
// some extreme or exceptional cases).
//
// Ribbon filters are compatible with RocksDB >= 6.15.0. Earlier
// versions reading the data will behave as if no filter was used
// (degraded performance until compaction rebuilds filters). All
// built-in FilterPolicies (Bloom or Ribbon) are able to read other
// kinds of built-in filters.
//
// Note: the current Ribbon filter schema uses some extra resources
// when constructing very large filters. For example, for 100 million
// keys in a single filter (one SST file without partitioned filters),
// 3GB of temporary, untracked memory is used, vs. 1GB for Bloom.
// However, the savings in filter space from just ~60 open SST files
// makes up for the additional temporary memory use.
//
// Also consider using optimize_filters_for_memory to save filter
// memory.
func NewRibbonFilterPolicy(bitsPerKey float64, bloomBeforeLevel int) FilterPolicy {
return NewNativeFilterPolicy(C.rocksdb_filterpolicy_create_ribbon_hybrid(C.double(bitsPerKey), C.int(bloomBeforeLevel)))
}
// Hold references to filter policies.
var filterPolicies = NewCOWList()
type filterPolicyWrapper struct {
name *C.char
filterPolicy FilterPolicy
}
func registerFilterPolicy(fp FilterPolicy) int {
return filterPolicies.Append(filterPolicyWrapper{C.CString(fp.Name()), fp})
}
//export gorocksdb_filterpolicy_create_filter
func gorocksdb_filterpolicy_create_filter(idx int, cKeys **C.char, cKeysLen *C.size_t, cNumKeys C.int, cDstLen *C.size_t) *C.char {
rawKeys := charSlice(cKeys, cNumKeys)
keysLen := sizeSlice(cKeysLen, cNumKeys)
keys := make([][]byte, int(cNumKeys))
for i, len := range keysLen {
keys[i] = charToByte(rawKeys[i], len)
}
dst := filterPolicies.Get(idx).(filterPolicyWrapper).filterPolicy.CreateFilter(keys)
*cDstLen = C.size_t(len(dst))
return cByteSlice(dst)
}
//export gorocksdb_filterpolicy_key_may_match
func gorocksdb_filterpolicy_key_may_match(idx int, cKey *C.char, cKeyLen C.size_t, cFilter *C.char, cFilterLen C.size_t) C.uchar {
key := charToByte(cKey, cKeyLen)
filter := charToByte(cFilter, cFilterLen)
return boolToChar(filterPolicies.Get(idx).(filterPolicyWrapper).filterPolicy.KeyMayMatch(key, filter))
}
//export gorocksdb_filterpolicy_name
func gorocksdb_filterpolicy_name(idx int) *C.char {
return filterPolicies.Get(idx).(filterPolicyWrapper).name
}