分享
  1. 首页
  2. 文章

Golang 优化之路——空结构

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

写在前面

开发 hashset 常用的套路:

map[int]int8
map[int]bool

我们一般只用 map 的键来保存数据,值是没有用的。所以来缓存集合数据会造成内存浪费。

空对象

空对象是个神奇的东西。它指的是没有字段的结构类型。

type Q struct{}

它牛逼的地方在于:

  • 可以和普通结构一样操作

    var a = []struct{}{struct{}{}}
    fmt.Println(len(a)) // prints 1
  • 不占用空间

    var s struct{}
    fmt.Println(unsafe.Sizeof(s)) // prints 0
  • 声明两个空对象,它们指向同一个地址

    type A struct{}
    a := A{}
    b := A{}
    fmt.Println(&a == &b) // prints true

造成这个结果的原因是 Golang 的编译器会把这种空对象都当成runtime.zerobase处理。

var zerobase uintptr

hashset

有了上面的介绍,就可以利用空结构来优化 hashset 了。

var itemExists = struct{}{}
type Set struct {
 items map[interface{}]struct{}
}
func New() *Set {
 return &Set{items: make(map[interface{}]struct{})}
}
func (set *Set) Add(item interface{}) {
 set.items[item] = itemExists
}
func (set *Set) Remove(item interface{}) {
 delete(set.items, item)
}
func (set *Set) Contains(item interface{}) bool {
 if _, contains := set.items[item]; !contains {
 return false
 }
 return true
}

一个简易的 hashset 实现就完成了。

性能比较

func BenchmarkIntSet(b *testing.B) {
 var B = NewIntSet(3)
 B.Set(10).Set(11)
 for i := 0; i < b.N; i++ {
 if B.Exists(1) {
 }
 if B.Exists(11) {
 }
 if B.Exists(1000000) {
 }
 }
}
func BenchmarkMap(b *testing.B) {
 var B = make(map[int]int8, 3)
 B[10] = 1
 B[11] = 1
 for i := 0; i < b.N; i++ {
 if _, exists := B[1]; exists {
 }
 if _, exists := B[11]; exists {
 }
 if _, exists := B[1000000]; exists {
 }
 }
}
BenchmarkIntSet-2 50000000 35.3 ns/op 0 B/op 0 allocs/op
BenchmarkMap-2 30000000 41.2 ns/op 0 B/op 0 allocs/op

结论

  • 性能,有些提升,但不是特别明显。尤其是线上压力不大的情况性能应该不会有明显变化;

  • 内存占用。我们的服务缓存较多、占用内存较大,通过这个优化实测可以减少 1.6 GB 的空间。不过这个优化的空间取决于数据量。


参考文献


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

本文来自:简书

感谢作者:Superman1316

查看原文:Golang 优化之路——空结构

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

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

用户登录

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

今日阅读排行

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

一周阅读排行

    加载中

关注我

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

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

给该专栏投稿 写篇新文章

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

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