Slice
提前分配 Slice 大小
尽可能在初始化的时候提供 Slice 的大小,这样可以达到近乎三倍的性能提升,如下:
func NoPreAlloc(size int){
data := make([]int, 0)
for k := 0; k < size; k ++ {
data = append(data, k)
}
}
以上一般是我们正常初始化数组的一个步骤,但是我们可以在初始化的时候提供容量信息,例如:
data := make([]int, 0, size)
这样可以通过 slice 预分配内存来优化性能
这个原因是因为切片本质是一个数组片段的描述,如果是我们不提供容量的话,go 默认分配的容量不一定能够 cover 我们所需要的大小,那么当我们需要放入超过容量的 item 时,会发生内存拷贝,而发生内存拷贝的这个过程便会影响到我们的程序的性能,如果这个拷贝的数量非常大的话,那可能会导致很多的问题。
在大切片的前提下,少使用切片
这是因为在已有切片的基础上,如果我们再创建一个小的切片,那么大切片就会一直占用内存,得不到释放。
Map
预分配
和 slice 一样,我们可以在 make 的时候增加 size 参数,来预分配内存。
字符串
StringBuilder
和 Java, C# 类似,在我们进行频繁的字符串拼接的时候,最好使用 strings.Builder 来进行拼接,而不是直接使用 += 运算符
测试我们的性能
使用内置的性能工具:
- 使用
pprof进行性能分析。 - 使用
bench进行基准测试,确定优化前后的性能差异。
使用外部的性能工具:
Go 也有一些外部的性能测试工具,可以给我们做一些参考,例如 pyroscope 或者其他工具,这些工具可以即时采集程序运行过程中的CPU占用等信息。