写在前面

开发 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] = 1B[11] = 1for 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 的空间。不过这个优化的空间取决于数据量。

参考文献

  • 【1】 The empty struct - Dave Cheney
  • 【2】 gods - emirpasic
  • 【3】 《Go 语言学习笔记》 - 雨痕。5.5 结构。

转载于:https://www.cnblogs.com/logo-fox/p/6985598.html

Golang 优化之路-空结构[转]相关推荐

  1. Golang 优化之路——HTTP长连接

    压测发现有长连接问题,深入学习了一下. 写在前面 TCP 相关 HTTP 包如何使用 TCP 长连接? 我们的程序为啥长连接失效? 如何解决问题? 后续 参考文献 写在前面 压测的是否发现服务端TIM ...

  2. golang怎么给空结构体赋值

    一.前言 最近没少使用golang,也没经过系统的学习,直接就上去开发了,遇到不少坑也学到不少东西,本次记录下给空结构体赋值的问题. 二.案例 1.结构体结构及错误 type Test struct ...

  3. Golang之空结构体和零长数组的实践

    空结构体和零长数组(两个复合类型)都仅仅是一个占位符,不占用空间,这里编译器进行了优化,如果结构体或数组的unsafe.sizeof=0则直接返回zerobase. // 必须用key来初始化结构体 ...

  4. Go 空结构体的 3 种使用场景

    转子地址:https://mp.weixin.qq.com/s/zWzyl6x9sZdXZCaAuva2lA 在 Go 语言中,有一个比较特殊的类型,经常会有刚接触 Go 的小伙伴问到,又或是不理解. ...

  5. 懂球帝Android客户端WebView优化之路

    导读 本文作者:涂晓龙 发布时间:2019-12-09 原文地址:https://mp.weixin.qq.com/s/MtEi6DgrNCO6HB2eQ0uBrw 这篇文章讲的是懂球帝Android ...

  6. 蚂蚁金服服务注册中心 SOFARegistry 解析 | 服务发现优化之路

    SOFAStack Scalable Open Financial  Architecture Stack 是蚂蚁金服自主研发的金融级分布式架构,包含了构建金融级云原生架构所需的各个组件,是在金融场景 ...

  7. CSS代码重构与优化之路(转)

    CSS代码重构与优化之路 阅读目录 CSS代码重构的目的 CSS代码重构的基本方法 CSS方法论 我自己总结的方法 写CSS的同学们往往会体会到,随着项目规模的增加,项目中的CSS代码也会越来越多,如 ...

  8. go语言-空结构体/ chan struct{}

    文章目录 空结构体 struct{} chan struct{} 常用用法 带缓冲的chan struct{}数据读写 空结构体 struct{} 空结构体的宽度是0,占用了0字节的内存空间. var ...

  9. Golang 优化之内存对齐

    这里填写标题 1. Golang 优化之内存对齐 1.1. 前文 1.2. 正文 1.2.1. 什么是内存对齐? 1.2.2. 为什么需要内存对齐? 1.2.2.1. 平台原因 1.2.2.2. 性能 ...

最新文章

  1. 在django中区分null = True,空白= True
  2. 控制ALV单元格可编辑
  3. 计算机一级115,计算机一级BASIC模拟115.doc
  4. 19.内在摄像机校准——内联函数 测验,结合外在和内在校准参数,编写相同方程的其他方法,相机参数_2
  5. 微信头像失效_如何判断微信授权的头像是否失效
  6. 微信小程序点餐系统怎么做
  7. 程序设计题大病:劝你不要买未来教育的Python二级书
  8. Qt网络编程之获取网络信息
  9. 电路板上的这些标志你都知道是什么含义吗?——详解电子产品认证类型
  10. JspStudy套件部署j2ee maven项目网址问题
  11. Tomcat8.5访问HTML页面出现乱码
  12. 哪种pdf编辑器更方便使用
  13. selenium+python+eclipse 实现 “问卷星”网站,登录与检查登录示例!
  14. 小程序和服务器之间的通信,微信小程序建立服务器通信的方法
  15. php正则保留字母数字,php正则只保留汉字字母数字
  16. 从中序与后序遍历序列构造二叉树
  17. R平方值python实现
  18. 流行手机谜语大解密 (爱情诗)
  19. 少儿Python视频课程A级简介
  20. ubuntu安装ActiveMQ

热门文章

  1. 如何自学python基础-零基础如何自学成为Python高手?我有几点干货
  2. python语言if语句-Python中的if判断语句入门
  3. python入门基础代码图-python入门基础知识(代码)
  4. python爬虫获取的网页数据为什么要加[0-使用 Python 爬取网页数据
  5. 图片的批量下载 和 爬虫爬取图片数据集
  6. spring中自定义Bean的性质
  7. UVa11134 Fabled Rooks(贪心算法)
  8. 网络编程学习笔记(套接口超时)
  9. Android布局之相对布局——RelativeLayout
  10. python中yield使用