功能:
CPU分析\内存分析\阻塞分析\互斥锁分析

pprof 采样数据主要有三种获取方式:

  • runtime/pprof: 手动调用runtime.StartCPUProfile或者runtime.StopCPUProfile等 API来生成和写入采样文件,灵活性高.用于代码运行一段时间就结束.
  • net/http/pprof: 通过 http 服务获取Profile采样文件,简单易用,适用于对应用程序的整体监控。用于代码持续运行的情形
  • go test: 通过 go test -bench . -cpuprofile prof.cpu生成采样文件.适用对测试函数进行针对性测试

一、runtime/pprof

引入 import “runtime/pprof”,在代码中添加:
CPU采样

  1. f, err := os.Create("cpu_profile.prof")
  2. if err != nil {
  3. panic(err.Error())
  4. }
  5. defer f.Close()
  6. pprof.StartCPUProfile(f)
  7. defer pprof.StopCPUProfile()

内存采样

  1. f, err := os.Create("mem_profile.mprof")
  2. if err != nil {
  3. panic(err.Error())
  4. }
  5. defer f.Close()
  6. pprof.WriteHeapProfile(f) //这一句放在程序结束时

分析

go tool pprof binary [source]
binary 是应用的二进制文件,用来解析各种符号;source 表示 profile 数据的来源,可以是本地的文件,也可以是 http 地址(在net/http/pprof模式下)。
例如

go tool pprof cpu_profile

注意: 1.程序运行时间太短,可能采样不到 2.先运行代码生成cpu_profile 3.耗时太短的代码可能不会显示

终端交互: (Total samples为0,即为采样失败)

  1. D:\gopath\src\code>go tool pprof cpu_profile
  2. Type: cpu
  3. Time: Jun 6, 2020 at 11:13pm (CST)
  4. Duration: 1.01s, Total samples = 2.76s (274.56%)
  5. Entering interactive mode (type "help" for commands, "o" for options)
  6. (pprof)

top 指令

list n (列表个数,默认10)

  1. (pprof) top
  2. Showing nodes accounting for 2080ms, 75.36% of 2760ms total
  3. Dropped 16 nodes (cum <= 13.80ms)
  4. Showing top 10 nodes out of 71
  5. flat flat% sum% cum cum%
  6. 810ms 29.35% 29.35% 810ms 29.35% runtime.procyield
  7. 390ms 14.13% 43.48% 1110ms 40.22% sync.(*Mutex).lockSlow
  8. 160ms 5.80% 49.28% 1270ms 46.01% sync.(*Mutex).Lock
  9. 150ms 5.43% 54.71% 510ms 18.48% sync.(*Mutex).Unlock
  10. 130ms 4.71% 59.42% 130ms 4.71% runtime.(*guintptr).cas
  11. 120ms 4.35% 63.77% 120ms 4.35% runtime.stdcall2
  12. 100ms 3.62% 67.39% 2160ms 78.26% main.(*list).Init_sync.func1
  13. 80ms 2.90% 70.29% 2010ms 72.83% math/rand.(*Rand).Int31n
  14. 70ms 2.54% 72.83% 100ms 3.62% main.(*list).Find_sync.func1
  15. 70ms 2.54% 75.36% 1930ms 69.93% math/rand.(*lockedSource).Int63
  • flat: 函数的运行时间. 采样时,该函数正在运行的次数*采样频率(10ms),即得到估算的函数运行”采样时间”。这里不包括函数等待子函数返回。
  • flat%: flat / 总采样时间值
  • sum%: 前面所有行的 flat% 的累加值,如第二行 sum% = 43.48% = 29.35% + 14.45%
  • cum: 采样时,该函数出现在调用堆栈的采样时间,包括函数等待子函数返回。因此 flat <= cum
  • cum%: cum / 总采样时间值

list指令

list 待匹配的函数

  1. (pprof) list Init
  2. Total: 2.76s
  3. ROUTINE ======================== main.(*list).Init_sync.func1 in D:\gopath\src\code\main.go
  4. 100ms 2.16s (flat, cum) 78.26% of Total
  5. . . 56: for i := 0; i < workNum; i++ {
  6. . . 57: go func(index int) {
  7. . . 58: defer group.Done()
  8. . . 59: startIndex := listLen / workNum * index
  9. . . 60: endIndex := listLen / workNum * ( index + 1 )
  10. 20ms 20ms 61: for j:= startIndex; j < endIndex; j++ {
  11. 80ms 2.14s 62: (*l)[j] = rand.Intn(10000)
  12. . . 63: }
  13. . . 64: }(i)
  14. . . 65: }
  15. . . 66: group.Wait()
  16. . . 67:}

web

打开调用图谱

二、go test

go test 命令有两个参数和 pprof 相关,它们分别指定生成的 CPU 和 Memory profiling 保存的文件:

  • cpuprofile:cpu profiling 数据要保存的文件地址
  • memprofile:memory profiling 数据要报文的文件地址

比如下面执行测试的同时,也会执行 CPU profiling,并把结果保存在 cpu.prof 文件中:

$ go test -bench . -cpuprofile=cpu.prof

执行结束之后,就会生成 main.test 和 cpu.prof 文件。要想使用 go tool pprof,需要指定的二进制文件就是 main.test。

需要注意的是,Profiling 一般和性能测试一起使用,这个原因在前文也提到过,只有应用在负载高的情况下 Profiling 才有意义。

三、net/http/pprof

引入import _ “net/http/pprof” 并加入 http.ListenAndServe(“localhost:6060”, nil) 到代码中.

gin使用pprof
引入 “github.com/gin-contrib/pprof” 添加 pprof.Register(r) // 性能

网页交互:

go tool pprof -http=:8090 http://localhost:6060/debug/pprof/profile?seconds=30

终端交互:

go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30

profile可调换参数:

  • goroutine: 获取程序当前所有 goroutine 的堆栈信息。
  • heap: 包含每个 goroutine 分配大小,分配堆栈等。每分配 runtime.MemProfileRate(默认为512K) 个字节进行一次数据采样。
  • threadcreate: 获取导致创建 OS 线程的 goroutine 堆栈
  • block: 获取导致阻塞的 goroutine 堆栈(如 channel, mutex 等),使用前需要先调用
    runtime.SetBlockProfileRate
  • mutex: 获取导致 mutex 争用的 goroutine 堆栈,使用前需要先调用 runtime.SetMutexProfileFraction
  • cmdline: 获取程序的命令行启动参数
  • profile: 获取指定时间内(从请求时开始)的cpuprof,倒计时结束后自动返回。参数: seconds, 默认值为30。cpuprofile 每秒钟采样100次,收集当前运行的 goroutine 堆栈信息。
  • symbol: 用于将地址列表转换为函数名列表,地址通过’+’分隔,如 URL/debug/pprof?0x18d067f+0x17933e7
  • trace: 对应用程序进行执行追踪,参数: seconds, 默认值1s

graphviz安装

https://graphviz.org/_pages/Download/Download_windows.html
graphviz安装目录下的bin文件夹添加到Path环境变量中

http://www.cppcns.com/jiqiao/fuwuqi/273835.html

参考

https://blog.golang.org/pprof(英文)
https://github.com/hyper0x/go_command_tutorial/blob/master/0.12.md

https://lrita.github.io/2017/05/26/golang-memory-pprof/
https://segmentfault.com/a/1190000016412013
https://juejin.im/entry/5ac9cf3a518825556534c76e(CPU 分析\内存分析\阻塞分析\互斥锁分析)
https://wudaijun.com/2018/04/go-pprof/