写在前面

开发 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 的空间。不过这个优化的空间取决于数据量。

参考文献

Golang 优化之路-空结构[转]的更多相关文章

  1. Golang 优化之路——bitset

    写在前面 开发过程中会经常处理集合这种数据结构,简单点的处理方法都是使用内置的map实现.但是如果要应对大量数据,例如,存放大量电话号码,使用map占用内存大的问题就会凸显出来.内存占用高又会带来一些 ...

  2. golang | Go语言入门教程——结构体初始化与继承

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是golang专题第10篇文章,我们继续来看golang当中的面向对象部分. 在上一篇文章当中我们一起学习了怎么创建一个结构体,以及怎么 ...

  3. Golang面向对象编程-struct(结构体)

    Golang面向对象编程-struct(结构体) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.什么是面向对象编程 面向对象编程(Object Oriented Program ...

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

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

  5. Greenplum 性能优化之路 --(二)存储格式

    一.存储格式介绍 Greenplum(以下简称 GP)有2种存储格式,Heap 表和 AO 表(AORO 表,AOCO 表). Heap 表:这种存储格式是从 PostgreSQL 继承而来的,目前是 ...

  6. 为什么C++中空类和空结构体大小为1?(转载)

    原文链接:http://www.spongeliu.com/260.html 对于结构体和空类大小是1这个问题,首先这是一个C++问题,在C语言下空结构体大小为0(当然这是编译器相关的).这里的空类和 ...

  7. 微博MySQL优化之路--dockone微信群分享

    微博MySQL优化之路 数据库是所有架构中不可缺少的一环,一旦数据库出现性能问题,那对整个系统都回来带灾难性的后果.并且数据库一旦出现问题,由于数据库天生有状态(分主从)带数据(一般还不小),所以出问 ...

  8. 新浪微博iOS客户端架构与优化之路

    新浪微博iOS客户端架构与优化之路   随着Facebook.Twitter.微博的崛起,向UGC.PGC.OGC,自媒体提供平台的内 容消费型App逐渐形成了独特的客户端架构模式.与电商和通讯工具类 ...

  9. 转:为什么C++中空类和空结构体大小为1?

    参考:http://www.spongeliu.com/260.html 为什么C++中空类和空结构体大小为1? On November 17, 2010, in C语言, 语言学习, by spon ...

随机推荐

  1. MySQL 字符集问题

    MySQL 支持许多字符集及其编码方案, 甚至是不同编码之间的转换. 在使用 MySQL 进行应用程序编程时, 常常会出现乱码现象, 这通常是由于客户端没有声明与 MySQL 服务器通信的字符串编码造 ...

  2. SQL Server进阶 索引

    create unique index 和create index 的区别? CREATE UNIQUE INDEX ProviderInfo_Id_uindex ON dbo.ProviderInf ...

  3. springboot项目怎么部署到外部tomcat

    spring-boot项目中,默认提供内嵌的tomcat,所以打包直接生成jar包,用Java -jar命令就可以启动. 但是也有一定的需求,会使用外部tomcat来部署项目.下面来看: 1.新建项目 ...

  4. JVM(二)垃圾回收

    要弄懂JVM的垃圾回收,首先要知道我们要回收什么,在哪回收,什么时候回收. 一.JVM内存模型 java虚拟机把内存模型分为了这么几部分 (1)程序计数器 程序计数器(Program Counter ...

  5. Canvas画圆形

    转载:https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes#圆弧 function d ...

  6. bash 文件名操作 常用方法

    参考链接: http://www.jb51.net/article/51592.htm 查找文件不获取路径: find $1 -name '*.bin' -exec basename {} \;

  7. 昨天看了一个大神的fix类,清晰了然

    .fix::after{ content:''; display:table; clear:both; }

  8. Python pipenv

    pipenv都包含什么? pipenv 是 Pipfile 主要倡导者.requests 作者 Kenneth Reitz 写的一个命令行工具,主要包含了Pipfile.pip.click.reque ...

  9. python 06

    1.集合 增: s.add(8) print(s) s.update('alex') # 迭代添加 print(s) 删 s = {1,2,3,'22','ss',(3,4)} s1 = s.pop( ...

  10. Python概念(八)字符串格式化:%和.format

    https://www.cnblogs.com/nulige/p/6115793.html