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.Builder和bytes.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)