Golang 性能优化工具 pprof 使用入门

文章发布时间:

Go 的 pprof 可以查看 CPU、堆内存、goroutine 和阻塞等运行数据。采集入口主要有两个:

  • runtime/pprof:采集工具型应用运行数据进行分析。
  • net/http/pprof:采集服务型应用运行时数据进行分析。

采集到 profile 后,可以用 go tool pprof 定位具体函数,而不是只凭接口耗时猜瓶颈。

常见 profile 类型包括:

  • CPU Profile:报告程序的 CPU 使用情况,通常按照 100Hz 频率采集应用程序在 CPU 和寄存器上的数据。
  • Memory Profile(Heap Profile):报告程序的内存使用情况,也就是程序运行过程中堆内存分配情况,默认每分配 512KB 取样一次。
  • Block Profiling:报告 goroutine 不在运行状态的情况,保存用户程序中的 goroutine 阻塞事件记录,可用于分析死锁等性能瓶颈。
  • Goroutine Profiling:报告 goroutine 的使用情况,包括当前有哪些 goroutine,以及它们的调用关系。

默认情况下,Go 不会追踪 block 和 mutex 信息。如果要看这两个信息,需要在代码中开启:

1
2
runtime.SetBlockProfileRate(1)      // 开启对阻塞操作的跟踪
runtime.SetMutexProfileFraction(1) // 开启对锁调用的跟踪

使用流程

1. 引入 pprof

1
2
3
4
5
import _ "net/http/pprof"

go func() {
_ = http.ListenAndServe("0.0.0.0:6060", nil)
}()

2. 浏览器访问 pprof 页面

在浏览器中输入:

1
http://127.0.0.1:6060/debug/pprof/

即可看到当前服务暴露出的监控数据。

profiles 解释如下:

  • allocs:查看过去所有内存分配的样本。
  • block:查看导致阻塞同步的堆栈跟踪。
  • cmdline:查看当前程序命令行的完整调用路径。
  • goroutine:查看当前所有运行中的 goroutine 堆栈跟踪。
  • heap:查看活动对象的内存分配情况。
  • mutex:查看导致互斥锁竞争的持有者堆栈跟踪。
  • profile:默认进行 30 秒 CPU profiling,得到一个分析用的 profile 文件。
  • threadcreate:查看创建新 OS 线程的堆栈跟踪。
  • trace:辅助跟踪程序的执行情况。

分析

线上分析更常用的是 go tool pprof。通常本地浏览器不能直接访问线上服务地址,而是通过线上服务生成分析文件,再把文件下载到本地分析。

如果要生成图形化视图,本地还需要安装 graphviz:

https://graphviz.org/download/

线上使用 go tool pprof 采集时,可以通过 seconds=30 参数指定采集时间。

查看 CPU 使用情况

1
go tool pprof http://9.9.9.9:8080/debug/pprof/profile

输出内容最后一列为函数名称,其他各项含义如下:

  • flat:当前函数占用 CPU 的耗时。
  • flat%:当前函数占用 CPU 的耗时百分比。
  • sum%:函数占用 CPU 的累计耗时百分比。
  • cum:当前函数加上调用当前函数的 CPU 总耗时。
  • cum%:当前函数加上调用当前函数的 CPU 总耗时百分比。

list 命令可以查看某个函数内部的 CPU 使用情况,形式为:

1
list 函数名

这类分析需要能匹配到源码。线上打包后的二进制如果缺少源码路径,可能无法直接看到具体代码行;本地运行时更容易查看到具体耗时位置。

排查时先按现象选 profile:CPU 高看 profile,内存增长看 heap,请求卡住则看 goroutine、block 和 mutex。再把采样结果与压测场景、业务日志对照,确认耗时或阻塞发生在哪条调用链上。