pprof 性能分析 @

概要 @

在 golang 项目开发测试过程中,程序经常会出现各种崩溃卡死的恶性 bug,例如内存飙升、CPU 占用太高、Goroutine 泄露等,有些仅从代码层面无法排查到,这时候就需要借助 pprof 工具来排查问题。

简要介绍 @

pprof 工具集,提供了 Go 程序内部多种性能指标的采样能力,我们常会用到的性能采样指标有这些:

  • profile:默认进行 30s 的 CPU Profiling,得到一个分析用的 profile 文件,访问路径为 $HOST/debug/pprof/profile`
  • heap:查看活动对象的内存分配情况, 访问路径为 $HOST/debug/pprof/heap`
  • goroutine:查看当前所有运行的 goroutines 堆栈跟踪,访问路径为 $HOST/debug/pprof/goroutine`
  • allocs: 查看过去所有内存分配的样本,访问路径为 $HOST/debug/pprof/allocs`(包括已经被 GC 回收的内存)
  • threadcreate:查看创建新 OS 线程的堆栈跟踪,访问路径为 $HOST/debug/pprof/threadcreate`
  • mutex:查看导致互斥锁的竞争持有者的堆栈跟踪,访问路径为 $HOST/debug/pprof/mutex`
  • block:查看导致阻塞同步的堆栈跟踪,访问路径为 $HOST/debug/pprof/block`

分析方式主要分为两种:

  • 根据 pprof 工具基于 web 图形界面进行分析
  • 基于交互式的命令行进行分析

Web 界面分析 @

_// pprof的init函数会将pprof里的一些handler注册到http.DefaultServeMux上_
**import** _ "net/http/pprof"

**go** **func**() {
    http**.**ListenAndServe("0.0.0.0:8080", nil)
}()

// http://0.0.0.0:8080/debug/pprof/goroutine?debug=1

在对应的访问路径上新增 ?debug=1 的话,就可以直接在浏览器访问

若不新增 debug 参数,那么将会直接下载对应的 profile 文件

# 图形界面分析
go tool pprof --http :7777 http://192.168.131.100:19528/debug/pprof/heap
# 生成图片
go tool pprof -alloc_space -cum -svg http://127.0.0.1:8080/debug/pprof/heap > heap.svg

命令行分析 Heap @

# 命令行交互模式(inuse_space、inuse_objects、alloc_space、alloc_objects)
go tool pprof -alloc_space http://localhost:6061/debug/pprof/heap
top10         # 查看累积分配内存较多的一些函数调用
top10 -sum    # 将函数调用关系中的数据进行累积
# 常用命令
top、list、traces、web、tree、png、svg
  • inuse_space — 已分配但尚未释放的内存空间
  • inuse_objects——已分配但尚未释放的对象数量
  • alloc_space — 分配的内存总量(已释放的也会统计)
  • alloc_objects — 分配的对象总数(无论是否释放)

命令行分析 CPU @

$ go tool pprof http://localhost:6060/debug/pprof/profile\?seconds\=60
Fetching profile over HTTP from http://localhost:6060/debug/pprof/profile?seconds=60
Saved profile in /Users/eddycjy/pprof/pprof.samples.cpu.002.pb.gz
Type: cpu
Duration: 1mins, Total samples = 37.25s (61.97%)
Entering interactive mode (type "help" for commands, "o" for options)(pprof)

执行该命令后,需等待 60 秒,pprof 会进行 CPU Profiling,结束后将默认进入 pprof 的命令行交互式模式,可以对分析的结果进行查看或导出。

输入查询命令 top10,以此查看对应资源开销。

(pprof) top10
Showing nodes accounting for 36.23s, 97.26% of 37.25s total
Dropped 80 nodes (cum <= 0.19s)
Showing top 10 nodes out of 34
      flat  flat%   sum%        cum   cum%  Name
    32.63s 87.60% 87.60%     32.70s 87.79%  syscall.syscall
     0.87s  2.34% 89.93%      0.88s  2.36%  runtime.stringtoslicebyte
     0.69s  1.85% 91.79%      0.69s  1.85%  runtime.memmove
     0.52s  1.40% 93.18%      0.52s  1.40%  runtime.nanotime
     ...
(pprof)

命令行分析 Goroutine @

$ go tool pprof http://localhost:6060/debug/pprof/goroutine
Fetching profile over HTTP from http://localhost:6060/debug/pprof/goroutine
Saved profile in /Users/eddycjy/pprof/pprof.goroutine.003.pb.gz
Type: goroutine
Entering interactive mode (type "help" for commands, "o" for options)(pprof)

查看 goroutine 时,我们可以使用 traces 命令,这个命令会打印出对应的所有调用栈。

(pprof) traces
Type: goroutine
-----------+-------------------------------------------------------
         2   runtime.gopark
             runtime.netpollblock
             internal/poll.runtime_pollWait
             ...
-----------+-------------------------------------------------------
         1   runtime.gopark
             runtime.netpollblock
             ...
             net/http.ListenAndServe
             main.main
             runtime.main