Day8:豆包MarsCode 技术训练营第八课GO语言性能优化 | 豆包MarsCode AI 刷题

109 阅读3分钟

1 性能优化建议

1.1 Benchmark

go test -bench=. -bencgmem

1.2 Slice预分配内存

尽可能在使用make()初始化切片时提供容量信息

data:=make([]int,0,capacity)

在已有切片基础上创建切片,不会创建新的底层数组,可能底层数组在内存中有引用,得不到释放

可以用copy替代切片覆盖

1.3 Map预分配内存

不断向map中添加元素的操作会触发map的扩容,可以提前分配好空间减少内存拷贝和Rehash的消耗

data:=make(map[int]int,size)

1.4 字符串处理(strings.Builder)

常见的拼接方式:

  • "+"
  • strings.Builder
  • bytes.Buffer

使用 + 拼接性能最差,strings.Builder最快

  • Go语言中字符串时不可变类型,占用内存大小是固定的,使用 + 每次都会重新分配内存
  • strings.Builderbytes.Buffer底层都是[]byte数组
  • 内存扩容策略,不需要每次拼接重新分配内存

1.5 空结构体

使用空结构体节省内存

  • 空结构体struct{}实例不占据任何的内存空间
  • 空结构体本身具备很强的语义,即这里不需要任何值,仅作为占位符
  • 利用空结构体和map实现set,只需要保留map的key,不需要value,将空结构体作为键

1.6 atomic包

  • sync/atomic包提供了基础的原子操作,这些操作对于某些低级别的并发编程任务很有用。
  • sync/atomic包通过硬件实现 ,效率比锁高。
  • sync.Mutex应该用来保护一段逻辑,不仅仅用于保护一个变量。
  • 对于非数值操作,可以使用sync.Value能承载一个interface{}

2 性能调优实战

2.1 简介

性能调优原则

  • 要依靠数据而不是猜测
  • 要定位最大瓶颈而不是细枝末节
  • 不要过早优化
  • 不要过度优化

2.2 性能分析工具pprof

pprof 是一个功能强大的性能分析工具,通常用于分析 Go 语言程序的运行性能。它可以用来识别程序中的性能瓶颈,包括 CPU 使用、内存分配、程序占用等情况。pprof 工具与 Go 语言集成度很高,是 Go 语言性能调优的重要工具之一。

1. 收集数据

要使用 pprof,首先需要收集程序的运行数据。在 Go 中,通过内置的 runtime/pprof 包来实现。

import "runtime/pprof"
pprof.StartCPUProfile(w)
// ... 程序运行 ...
pprof.StopCPUProfile()

对于 HTTP 服务,可以使用 net/http/pprof 包来通过 HTTP 接口暴露性能数据。

import _ "net/http/pprof"
go func() {
    log.Println(http.ListenAndServe("localhost:6060", nil))
}()

2. 分析数据

收集到数据后,可以使用 pprof 工具来分析这些数据。可以通过命令行工具来分析,或者使用图形界面。

命令行分析

go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30

上述命令会收集 30 秒的 CPU 配置文件,并进入 pprof 的交互式命令行。

图形界面分析

可以使用 pprof 的可视化工具来更直观地分析数据。

go tool pprof -http=:8080 cpu.prof

这会在本地启动一个 Web 服务器,并在浏览器中打开可视化界面。

3. 常用命令

pprof 的交互式命令行中,可以使用以下命令:

  • top: 显示占用资源最多的函数
  • list: 列出函数或源文件的详细信息
  • web: 生成并打开一个 SVG 图表,用于可视化调用图
  • tree: 显示调用树

4. 分析内存使用

除了 CPU 配置文件,pprof 也常用于分析内存使用。

go tool pprof -http=:8080 mem.prof

这里 mem.prof 是通过以下方式生成的:

pprof.WriteHeapProfile(w)