Github源码:https://github.com/bits-and-blooms/bloom
比如说要创建一个布隆过滤器
m=1000,k=4 (创建的bitset大小为1000,判断是否存在时check4次)
func New(m uint, k uint) *BloomFilter {
return &BloomFilter{max(1, m), max(1, k), bitset.New(m)}
}
那么bitset需要开辟多大空间呢?
开辟 wordsNeeded(length) 个 uint64 数组
func New(length uint) (bset *BitSet) {
defer func() {
if r := recover(); r != nil {
bset = &BitSet{
0,
make([]uint64, 0),
}
}
}()
bset = &BitSet{
length,
make([]uint64, wordsNeeded(length)),
}
return bset
}
直接看return公式 = (1000+(64-1)) >> 6
其实这个公式的就是求 大小为1063的bitmap需要多少uint64
2^64的二进制位一共有64位,
那么公式就变为 1063/64 = 16,只需要16个uint64数字就可以存储1000个值了
那为什么1000要+(64-1)呢?
因为 1000直接除以64,还有mod值呢,所以直接加上63不需要算mod问题
假如开辟大小为1025个,刚好使用17个uint64(亲测!!)
func wordsNeeded(i uint) int {
if i > (Cap() - wordSize + 1) {
return int(Cap() >> log2WordSize)
}
return int((i + (wordSize - 1)) >> log2WordSize)
}
输入一个data值,对它做bitset
h := baseHashes(data), h数组大小为4
首先通过murmur Hash算法求出 4个值
然后for循环k次(4次),在bitset中做判断
func (f *BloomFilter) Add(data []byte) *BloomFilter {
h := baseHashes(data)
for i := uint(0); i < f.k; i++ {
f.b.Set(f.location(h, i))
}
return f
}
h = hash算出来的4个值,i = 第几次check
看return公式, ii*h[2+(((ii+(ii%2))%4)/2)],乘0、乘1、乘2...
完美的把四次check的idx打散在bitset上
h[ii%2] | ii*h[2+(((ii+(ii%2))%4)/2)] |
h[0] | 0*h[2] |
h[1] | 1*h[3] |
h[0] | 2*h[3] |
h[1] | 3*h[2] |
func location(h [4]uint64, i uint) uint64 {
ii := uint64(i)
return h[ii%2] + ii*h[2+(((ii+(ii%2))%4)/2)]
}
【完】