这是我参与「第五届青训营 」伴学笔记创作活动的第12天
性能优化
这节课讲解了性能优化指南,介绍了一些对项目的优化方式。
性能优化是指前提为满足正确可靠、简洁清晰等质量因素、它是一种综合评估,要注意有时时间效率和空间效率可能对立,要合理考虑。同时针对Go语言的特性,本节课介绍了Go相关的性能优化建议。
性能优化建议
Benchmark
性能表现需要实际的衡量,而Golang提供了支持基准性能测试的benchmark工具,其命令如下:
go test -bench=. -benchmem
如下是对 fib.go 及其 fib_test.go 其中的函数:
func Fib(n int) int {
if n < 2 {
return n
}
return Fib(n-1) + Fib(n-2)
}
func BenchmarkFib10(b *testing.B) {
for n := 0; n < b.N; n++ {
Fib(10)
}
}
其中结果是 BenchmarkFib10-8 1855870 602.5 ns/op 0 B/op 0 allocs/op 。分别代表着
测试函数名-8 表示GOMAXPROCS的值为8(1.5版本后默认值为CPU核数)、一共执行的次数即为b.N的值、每次执行花费的ns时长值、每次执行申请的内存大小、每次执行申请内存的次数。
Slice
还可以使用slice预分配内存,尽可能在使用 make() 初始化切片时提供容量信息。如将 make([]int, 0) 变为 make([]int, 0, size),通过benchmark查看可以发现明显减少对内存的消耗和使用。
使用切片的本质是一个数组片段的描述,包括了数组指针、片段的长度、在不改变内存分配情况下的最大程度的片段容量。切片这一操作并不复制切片指向的元素,而是创建一个新的切片会复用原来切片的底层数组。
type slice struct {
array unsafe.Pointer
len int
cap int
}
在之前的笔记中也提到过,slice存在一个陷阱,那就是大内存释放问题。在已有的切片基础上再进行创建,不会创建新的底层数组,比如原切片很大时代码在基础上新建小的切片,这时原底层数组在内存之中存在引用而无法释放。可以采用copy 代替 re-slice 来进行解决。