【源码解析】布隆过滤器之bitset篇

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)]
}

【完】

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值