Golang 优化之路-空结构[转]
写在前面
开发 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()
B.Set().Set()
for i := ; i < b.N; i++ {
if B.Exists() {
}
if B.Exists() {
}
if B.Exists() {
}
}
}
func BenchmarkMap(b *testing.B) {
var B = make(map[int]int8, )
B[] =
B[] =
for i := ; i < b.N; i++ {
if _, exists := B[]; exists {
}
if _, exists := B[]; exists {
}
if _, exists := B[]; exists {
}
}
}
BenchmarkIntSet- 35.3 ns/op B/op allocs/op
BenchmarkMap- 41.2 ns/op B/op allocs/op
结论
- 性能,有些提升,但不是特别明显。尤其是线上压力不大的情况性能应该不会有明显变化;
- 内存占用。我们的服务缓存较多、占用内存较大,通过这个优化实测可以减少 1.6 GB 的空间。不过这个优化的空间取决于数据量。
参考文献
- 【1】 The empty struct - Dave Cheney
- 【2】 gods - emirpasic
- 【3】 《Go 语言学习笔记》 - 雨痕。5.5 结构。
Golang 优化之路-空结构[转]的更多相关文章
- Golang 优化之路——bitset
写在前面 开发过程中会经常处理集合这种数据结构,简单点的处理方法都是使用内置的map实现.但是如果要应对大量数据,例如,存放大量电话号码,使用map占用内存大的问题就会凸显出来.内存占用高又会带来一些 ...
- golang | Go语言入门教程——结构体初始化与继承
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是golang专题第10篇文章,我们继续来看golang当中的面向对象部分. 在上一篇文章当中我们一起学习了怎么创建一个结构体,以及怎么 ...
- Golang面向对象编程-struct(结构体)
Golang面向对象编程-struct(结构体) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是面向对象编程 面向对象编程(Object Oriented Program ...
- CSS代码重构与优化之路(转)
CSS代码重构与优化之路 阅读目录 CSS代码重构的目的 CSS代码重构的基本方法 CSS方法论 我自己总结的方法 写CSS的同学们往往会体会到,随着项目规模的增加,项目中的CSS代码也会越来越多 ...
- Greenplum 性能优化之路 --(二)存储格式
一.存储格式介绍 Greenplum(以下简称 GP)有2种存储格式,Heap 表和 AO 表(AORO 表,AOCO 表). Heap 表:这种存储格式是从 PostgreSQL 继承而来的,目前是 ...
- 为什么C++中空类和空结构体大小为1?(转载)
原文链接:http://www.spongeliu.com/260.html 对于结构体和空类大小是1这个问题,首先这是一个C++问题,在C语言下空结构体大小为0(当然这是编译器相关的).这里的空类和 ...
- 微博MySQL优化之路--dockone微信群分享
微博MySQL优化之路 数据库是所有架构中不可缺少的一环,一旦数据库出现性能问题,那对整个系统都回来带灾难性的后果.并且数据库一旦出现问题,由于数据库天生有状态(分主从)带数据(一般还不小),所以出问 ...
- 新浪微博iOS客户端架构与优化之路
新浪微博iOS客户端架构与优化之路 随着Facebook.Twitter.微博的崛起,向UGC.PGC.OGC,自媒体提供平台的内 容消费型App逐渐形成了独特的客户端架构模式.与电商和通讯工具类 ...
- 转:为什么C++中空类和空结构体大小为1?
参考:http://www.spongeliu.com/260.html 为什么C++中空类和空结构体大小为1? On November 17, 2010, in C语言, 语言学习, by spon ...
随机推荐
- jQuery使用(一):jQuery对象与选择器
一.简单的一些介绍 1.jQuery是由普通的是由一些系列操作DOM节点的函数和一些其他的工具方法组成的js库. 2.为什么要使用jQuery库? jQuery面向用户良好的设计在使用过程中彻底解放了 ...
- Python绘制wav文件音频图(静态)[matplotlib/wave]
#!/usr/bin/env python # -*- coding: utf-8 -*- """ 绘制波形图 plottingWaveform.py "&qu ...
- 指定so动态链接库连接器
在学习x86_64汇编时, 发现一旦使用glibc库函数, 如printf时, 一般是需要使用为ld传递命令行参数-lc来动态连接libc.so的, 但是, 生成的可执行文件却无法运行: 气煞我也! ...
- SQL Server进阶(十一)可编程对象——变量、 批、流元素、 游标
变量 --------------------------------------------------------------------- -- Variables -------------- ...
- Android手机有的不显示Toast
解决办法一: 在手机中把该app的通知打开 可以直接设置通知权限:<uses-permission android:name="android.permission.RECEIVE_B ...
- Retrofit提交Json
1.APIService为自定义接口类, 定义@Headers @Headers({"Content-Type: application/json","Accept: a ...
- C++ vector和list的主要用法区别
vector可以直接通过下标访问,list不可以 1.vector ; i < userTypes.size(); i++) { str = userTypes[i].typeName; } 2 ...
- bash test命令探秘
shell 测试条件命令 http://blog.csdn.net/yangruibao/article/details/7427503 test 和 [ 命令 虽然 Linux 和 UNIX 的每个 ...
- poj2559/hdu1506 单调栈经典题
我实在是太菜了啊啊啊啊啊 到现在连个单调栈都不会啊啊啊 写个经典题 #include<cstdio> #include<algorithm> #include<cstri ...
- Food Log with Speech Recognition and NLP
1. 分词 word segmentation 国内有jieba 分词 2. Named Entity Recognition 训练自己的Model How can I train my own NE ...