性能优化是编写高质量,高可用性代码不可或缺的一部分,本章跟随课程学习Go的性能优化相关内容。
什么是性能优化
前提:满足正确可靠、简洁清晰等质量因素 效率评估:性能优化是时空效率综合评估,有时候时间效率和空间效率会相互对立 测试工具:以下默认为Go提供的benchmark工具,进行实际数据衡量
性能优化的原则
- 依靠数据而不是猜测
- 定位最大瓶颈而不是细枝末节
- 不要过早优化
- 不要过度优化
Slice
slice作为基本操作之一,用途十分广泛,它的优化也因此至关重要。
预分配内存
尽可能使用make在初始化切片时提供容量信息
func NoPreAlloc(sizze int){
data := make([]int, 0)
for k := 0; k < size; k++ {
data = append(data, k)
}
}
上为未提供初始容量信息,下为提供
func NoPreAlloc(sizze int){
data := make([]int, 0, size)
for k := 0; k < size; k++ {
data = append(data, k)
}
}
大内存未释放问题
大内存如果没能得到及时释放会严重影响运行空间。由于Go和python一样都是自动垃圾回收机制,所以需要注意该陷阱。比如沼泽里有origin大内存切片,希望在已有基础上创建新的切片,可以用copy代替re-slice。
func GetLastBySlice(origin []int) []int{
return origin[len(origin)-2:]
}
func GetLastByCopy(origin []int) []int{
result := make([]int, 2)
copy(result, origin[len(origin)-2:])
return result
}
如下图所示,copy明显更优
map
类似于slice操作,基本思想都是不断添加元素需要先扩容再添加,频繁的内存拷贝,rehash等操作会带来极大消耗,所以建议根据实际需求提前预估好需要的空间。
strings
多用内置函数,和python类似,不要直接用“+”拼接字符串,这样需要重新分配内存,内置函数考虑到底层的[]byte操作,转为字符串类型返回
性能分析工具pprof
希望知道什么地方耗费了多少CPU,memory, pprof用于可是怀和分析性能分析数据的工具