Go性能优化 | 青训营

118 阅读2分钟

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占用等信息。