
pprof 是 Go 语言内置的性能分析工具,用于分析和优化 Go 程序的性能。它可以帮助开发者识别 CPU 瓶颈、内存泄漏、goroutine 阻塞等问题。
1. pprof 简介
pprof 提供了以下几种分析类型:
- CPU 分析:识别消耗 CPU 时间最多的函数
- 内存分析:识别内存分配情况
- 阻塞分析:识别同步原语导致的阻塞
- Goroutine 分析:查看所有 goroutine 的堆栈跟踪
- 互斥锁分析:识别锁竞争情况
- 线程创建分析:识别线程创建情况
2. 基本使用
2.1 导入 pprof
import _ "net/http/pprof"
只需导入这个包,它就会自动注册 HTTP 处理器到默认的 HTTP 服务上。
2.2 启动 HTTP 服务
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
2.3 访问分析数据
启动程序后,可以通过浏览器访问:
http://localhost:6060/debug/pprof/
– 查看所有可用 profilehttp://localhost:6060/debug/pprof/heap
– 内存分析http://localhost:6060/debug/pprof/profile?seconds=30
– CPU 分析(持续30秒)http://localhost:6060/debug/pprof/block
– 阻塞分析http://localhost:6060/debug/pprof/goroutine?debug=2
– goroutine 分析
3. 详细使用方式
3.1 CPU 分析
采集方式:
- 通过 HTTP 接口:
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
- 代码中手动采集:
f, err := os.Create("cpu.prof")
if err != nil {
log.Fatal(err)
}
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
分析命令:
top
– 查看最耗 CPU 的函数list 函数名
– 查看函数的具体耗时web
– 生成调用图(需要安装 graphviz)
3.2 内存分析
采集方式:
- 通过 HTTP 接口:
go tool pprof http://localhost:6060/debug/pprof/heap
- 代码中手动采集:
f, err := os.Create("mem.prof")
if err != nil {
log.Fatal(err)
}
pprof.WriteHeapProfile(f)
f.Close()
分析命令:
top
– 查看内存分配最多的函数top -cum
– 查看累计内存分配list 函数名
– 查看函数的内存分配情况web
– 生成内存分配图
3.3 Goroutine 分析
采集方式:
go tool pprof http://localhost:6060/debug/pprof/goroutine
分析命令:
top
– 查看 goroutine 数量最多的调用栈traces
– 查看所有 goroutine 的堆栈跟踪
3.4 阻塞分析
采集方式:
go tool pprof http://localhost:6060/debug/pprof/block
分析命令:
top
– 查看阻塞时间最长的操作
4. 高级用法
4.1 火焰图生成
- 安装 go-torch:
go get github.com/uber/go-torch
- 生成火焰图:
go-torch -u http://localhost:6060 -p > torch.svg
4.2 基准测试集成
在基准测试中使用 pprof:
func BenchmarkSomething(b *testing.B) {
f, _ := os.Create("bench.prof")
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
for i := 0; i < b.N; i++ {
// 测试代码
}
}
4.3 自定义分析端点
可以自定义 pprof 的 HTTP 端点:
mux := http.NewServeMux()
mux.HandleFunc("/custom/pprof/", pprof.Index)
mux.HandleFunc("/custom/pprof/cmdline", pprof.Cmdline)
mux.HandleFunc("/custom/pprof/profile", pprof.Profile)
mux.HandleFunc("/custom/pprof/symbol", pprof.Symbol)
mux.HandleFunc("/custom/pprof/trace", pprof.Trace)
5. 实际案例分析
5.1 内存泄漏分析
- 获取 heap profile:
go tool pprof -http=:8080 http://localhost:6060/debug/pprof/heap
- 在浏览器中查看内存分配情况,重点关注持续增长的对象
5.2 CPU 热点分析
- 采集 30 秒 CPU profile:
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
- 使用
top
和list
命令定位热点函数
6. 最佳实践
- 在生产环境中谨慎使用 pprof,因为它会影响性能
- 分析时设置合理的采样时间(通常 30-60 秒)
- 比较不同时间点的 profile 以识别趋势
- 结合日志和其他监控工具一起分析
- 在性能测试环境中先进行分析,再应用到生产环境
7. 注意事项
- pprof 默认采样频率是 100Hz(每秒100次)
- 内存分析显示的是分配情况,不一定是内存使用情况
- CPU 分析在程序繁忙时最有效
- 某些分析(如阻塞分析)需要先设置采样率:
runtime.SetBlockProfileRate(1) // 每纳秒采样一次阻塞事件