分享
  1. 首页
  2. 文章

golang 性能优化之 bitset 代替 hashset

hatlonely · · 2012 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

hashset 是一种非常高效的数据结构,插入和查询的复杂度都是 O(1),基本上能满足大部分场景的性能需求,但在一些特殊的场景下,频次非常高的调用依然会成为性能瓶颈(用 pprof 分析),比如广告里面的定向逻辑,在一次请求中过滤逻辑可能会执行上千次,而其中有些过滤刚好都是一些枚举值,比如性别定向,年龄定向等等,对于这种可以用枚举表示的值可以用 bitset 优化,能有20多倍的性能提升

bitset 的本质也是一种 hashset,只不过哈希桶用一个 uint64 来表示了,uint64 中的每一位用来代表一个元素是否存在,如果为1表示存在,为0表示不存在,而插入和查询操作就变成了位运算

bitset 实现

bitset 的实现比较容易,下面这个是一个只支持枚举值不超过64的版本,当然也可以拓展到任意长度,使用一个 uint64 数组作为 hash 桶即可

type BitSet struct {
 bit uint64
}
func (bs *BitSet) Add(i uint64) {
 bs.bit |= 1 << i
}
func (bs *BitSet) Del(i uint64) {
 bs.bit &= ^(1 << i)
}
func (bs BitSet) Has(i uint64) bool {
 return bs.bit&(1<<i) != 0
}

性能测试

func BenchmarkSetContains(b *testing.B) {
 bitset := NewBitSet()
 hashset := map[uint64]struct{}{}
 for _, i := range []uint64{1, 2, 4, 10} {
 bitset.Add(i)
 hashset[i] = struct{}{}
 }
 b.Run("bitset", func(b *testing.B) {
 for i := 0; i < b.N; i++ {
 for i := uint64(0); i < uint64(10); i++ {
 _ = bitset.Has(i)
 }
 }
 })
 b.Run("hashset", func(b *testing.B) {
 for i := 0; i < b.N; i++ {
 for i := uint64(0); i < uint64(10); i++ {
 _, _ = hashset[i]
 }
 }
 })
}
BenchmarkSetContains/bitset-8 500000000 3.81 ns/op 0 B/op 0 allocs/op
BenchmarkSetContains/hashset-8 20000000 89.4 ns/op 0 B/op 0 allocs/op

可以看到 bitset 相比 hashset 有20多倍的性能提升

参考链接

转载请注明出处
本文链接:http://www.hatlonely.com/2018...

有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:hatlonely

查看原文:golang 性能优化之 bitset 代替 hashset

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
2012 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏