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

文章发布时间:

最后更新时间:

在 Golang 中,可以通过 pprof 工具对程序运行时进行性能分析,包括 CPU、内存、goroutine 等实时信息。

Go 内置了获取程序运行数据的工具,主要包括以下两个标准库:

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

pprof 开启后,会按采样频率收集当前堆栈信息,获取各个函数占用的 CPU 和内存资源,然后基于这些采样数据形成性能分析报告。

常见 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 函数名

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

小结

pprof 适合回答三个问题:

  1. CPU 时间主要花在哪些函数上。
  2. 内存主要分配在哪里。
  3. goroutine、锁竞争、阻塞是否出现异常堆积。

实际排查时,不要只看单个 profile。CPU、heap、goroutine、block、mutex 往往需要结合压测场景和业务日志一起看,才能判断问题是计算密集、内存分配、阻塞等待,还是并发控制设计不合理。