这是我参与「第三届青训营 -后端场」笔记创作活动的的第4篇笔记, 第三次课主要讲了GO语言的高质量变成和性能调优实战,本文是针对性能优化建议部分做的笔记。
一、Benchmark
- 性能表现需要实际数据衡量
- Go语言提供了支持基准性能测试的benchmark工具
- 使用命令
$ go test -bench=. -benchmem
- 结果
二、Slice优化建议
1. 预分配内存
- 尽可能在使用make初始化切片的时候提供容量信息
- 切片本质是数组片段的描述
slice底层结构
type slice struct{
array unsafe.Pointer
len int
cap int
}
2. 大内存未释放
- 在已有切片的基础上创建切片,不会创建新的底层数组
- 可以使用copy代替re-slice
\
\
三、map优化建议
1.map预分配内存
这个和slice原理类似
- 不断向map中添加元素会导致map扩容
- 提前分配好空间会减少内存拷贝和rehash的消耗
四、字符串性能优化
1. 使用strings.Builder
- 常见的字符串拼接方式
- 性能分析
- 使用+拼接性能最差, strings.Builder, bytes.Buffer相近,strings.Builder更快
- 每次+都会重新分配内存
- strings.Builder底层是[]byte数组
- 使用的是内存扩容策略,不需要每次重新分配内存
五、使用空结构体性能优化
- 使用空结构体struct{}实例,不占任何内存空间
- 可以做各种场景下的占位符使用
- 节省资源
- 作为占位符
\
用途
- 实现Set,可以考虑用map的key实现,value设置为空结构体
- 即使将map的value设置为bool类型,也会多占据一个字节空间
六、使用atomic包优化
在针对单个变量的并发操作场景下,可以使用atomic包代替并发锁
- 锁的实现是通过操作系统实现的, 属于系统调用
- atomic操作是通过硬件实现的,效率高
- 锁应该用来保护一段逻辑,而不是一个变量
- 对于非数值操作,可以使用atomic.Value, 能承载一个interface{}