Go pprof 性能分析工具

发布时间: 更新时间: 总字数:1839 阅读时间:4m 作者: 分享 复制网址

golang中,pprof 是一款可视化和分析剖析数据的工具(pprof is a tool for visualization and analysis of profiling data.)

介绍

  • 常用来分享 go 程序如:CPU 分析、内存分析、阻塞分析、互斥锁分析、查看 gorouting 等
  • 相关的源码:
    • runtime/pprof 采集程序的运行时分析数据
    • net/http/pprof 通过其 HTTP 服务器以 pprof 可视化工具所期望的格式提供运行时剖析数据
  • pprofprofile.proto 读取分析样本,提供可视化的分析报告
  • pprof 的使用模式Usage modes
    • Report generation:生成指定格式的报告并退出,格式可以是文本或图形
      • pprof <format> [options] source
    • Interactive terminal use:交互式终端使用,pprof 将启动一个交互式 shell,用户可以在其中输入 help 命令获取在线帮助
      • pprof [options] source
    • Web interface:Web 界面,pprof 将开始在指定端口上服务 HTTP 请求,在浏览器中访问与端口相对应的 HTTP 网址(通常为 http://<host>:<port>/),查看界面
      • pprof -http=[host]:[port] [options] source

net/http/pprof

  • 示例 main.go
package main

import (
	"log"
	"net/http"
	_ "net/http/pprof"
)

func main() {
	log.Println(http.ListenAndServe("localhost:6060", nil))
}
  • 启动
go run main.go

指标说明

  • 使用浏览器访问 http://localhost:6060/debug/pprof/ 既可以打开 pprof 的页面,指标说明
    • allocs:过去所有内存分配的抽样
      • /debug/pprof/allocs
    • block:导致同步原语阻塞的堆栈跟踪
      • /debug/pprof/block
    • cmdline:当前程序的命令行调用
      • /debug/pprof/cmdline
    • goroutine:当前所有 goroutine 的堆栈跟踪,可以指定 ?second=30
      • /debug/pprof/goroutine
      • 使用 debug=2 作为查询参数,以与未恢复的 panic 相同的格式导出
    • heap(堆):实时对象的内存分配采样。可以指定 gc GET 参数,以便在采集堆样本前运行 GC
      • /debug/pprof/heap
    • mutex:有争议的互斥项持有者的堆栈轨迹
      • /debug/pprof/mutex
    • profile:CPU 指标分析。可以在秒 GET 参数中指定持续时间,默认获取 30-second CPU profile,可以指定 ?second=30
      • /debug/pprof/profile
      • 获取配置文件后,使用 go tool pprof xxx 命令研究配置文件
    • threadcreate:导致创建新操作系统线程的堆栈跟踪
      • /debug/pprof/threadcreate
    • trace(跟踪):当前程序的执行跟踪。可以在秒 GET 参数中指定持续时间
      • /debug/pprof/trace
      • 获取跟踪文件后,使用 go tool trace xxx 命令调查跟踪
  • 参数可通过 GET 查询参数传递:
    • debug=N(所有配置文件):响应格式
      • N = 0:二进制(默认)
      • N > 0:明文
    • gc=N(堆配置文件):N>0:剖析前运行垃圾回收周期
    • seconds=N(allocs、block、goroutine、heap、mutex、threadcreate 配置文件):返回 delta 配置文件
    • seconds=N(cpu (profile), trace profiles):在给定的持续时间内进行剖析

go tool pprof

  • help
go tool pprof --help ...
$ go tool pprof --help
usage:

Produce output in the specified format.

   pprof <format> [options] [binary] <source> ...

Omit the format to get an interactive shell whose commands can be used
to generate various views of a profile

   pprof [options] [binary] <source> ...

Omit the format and provide the "-http" flag to get an interactive web
interface at the specified host:port that can be used to navigate through
various views of a profile.

   pprof -http [host]:[port] [options] [binary] <source> ...
...
  Legacy convenience options:
   -inuse_space           Same as -sample_index=inuse_space
   -inuse_objects         Same as -sample_index=inuse_objects
   -alloc_space           Same as -sample_index=alloc_space
   -alloc_objects         Same as -sample_index=alloc_objects
   -total_delay           Same as -sample_index=delay
   -contentions           Same as -sample_index=contentions
   -mean_delay            Same as -mean -sample_index=delay
...
  • go tool pprof 如果没有安装 Graphviz,会报错:failed to execute dot. Is Graphviz installed?,安装命令
# macos
brew install graphviz

# ubuntu
apt-get install graphviz

# centos
yum install graphviz
  • go tool pprof 中支持的指令
    • help 帮助
    • web 使用浏览器打开
    • toptop10 查看耗能 top10
  • Interactive terminal use
$ go tool pprof http://localhost:6060/debug/pprof/goroutine
Fetching profile over HTTP from http://localhost:6060/debug/pprof/goroutine
Saved profile in /Users/xiexianbin/pprof/pprof.goroutine.002.pb.gz
Type: goroutine
Time: Nov 26, 2023 at 1:48pm (CST)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 5, 100% of 5 total
Showing top 10 nodes out of 38
      flat  flat%   sum%        cum   cum%
         4 80.00% 80.00%          4 80.00%  runtime.gopark
         1 20.00%   100%          1 20.00%  runtime.goroutineProfileWithLabels
         0     0%   100%          1 20.00%  bufio.(*Reader).Peek
         0     0%   100%          1 20.00%  bufio.(*Reader).ReadLine
         0     0%   100%          1 20.00%  bufio.(*Reader).ReadSlice
         0     0%   100%          2 40.00%  bufio.(*Reader).fill
         0     0%   100%          1 20.00%  internal/poll.(*FD).Accept
         0     0%   100%          3 60.00%  internal/poll.(*FD).Read
         0     0%   100%          4 80.00%  internal/poll.(*pollDesc).wait
         0     0%   100%          4 80.00%  internal/poll.(*pollDesc).waitRead (inline)
(pprof) web  # 使用浏览器打开等

$ go tool pprof http://localhost:6060/debug/pprof/heap
Fetching profile over HTTP from http://localhost:6060/debug/pprof/heap
Saved profile in /Users/xiexianbin/pprof/pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.001.pb.gz
Type: inuse_space
Time: Nov 26, 2023 at 2:31pm (CST)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 512.56kB, 100% of 512.56kB total
      flat  flat%   sum%        cum   cum%
  512.56kB   100%   100%   512.56kB   100%  runtime.allocm
         0     0%   100%   512.56kB   100%  runtime.forEachP
...

参数说明:

  • flat: the value of the location itself.
  • flat%:给定含函数的 CPU 运行耗时总比例
  • sum%:给定函数累积使用 CPU 总比例
  • cum: the value of the location plus all its descendants.
  • cum%:当前函数加上它之上的调用 CPU 运行耗时总比例
  • Web interface,支持查看
    • Top
    • Graph
    • Flame Graph(火焰图)
    • Flame Graph (new)
    • Peek
    • Source 等
wget -O profile.out http://localhost:6060/debug/pprof/profile?seconds=60
go tool pprof -http=":8081" profile.out
logo

示例

# 安装 hey,用来给服务器打流量
go install github.com/rakyll/hey@latest

# 使用 hey 打流量
hey -z 3m http://localhost:6060

# 获取 profile 并分析
wget -O profile.out http://localhost:6060/debug/pprof/profile?seconds=30
# 进入 Interactive terminal use
go tool pprof profile.out
# 打开 Web interface
go tool pprof -http=":8081" profile.out

# 同时获取 trace 并分析,将打开 web 浏览器
wget -O trace.out http://localhost:6060/debug/pprof/trace
go tool trace trace.out

# 同时获取 goroutine 并分析
go tool pprof --seconds 20 http://localhost:6060/debug/pprof/goroutine
go tool pprof http://localhost:6060/debug/pprof/goroutine?second=20

程序指定路径集成

package pprof

import (
	"net/http"
	"net/http/pprof"
	"os"

	log "github.com/sirupsen/logrus"
)

func Init() {
	// https://mmcloughlin.com/posts/your-pprof-is-showing
	http.DefaultServeMux = http.NewServeMux()
	if os.Getenv("ARGO_PPROF") == "true" {
		log.Info("enabling pprof debug endpoints - do not do this in production")
		http.HandleFunc("/debug/pprof/", pprof.Index)
		http.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
		http.HandleFunc("/debug/pprof/profile", pprof.Profile)
		http.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
		http.HandleFunc("/debug/pprof/trace", pprof.Trace)
	} else {
		log.Info("not enabling pprof debug endpoints")
	}
}

go test 生成性能分析数据

# cpu 分析
$ go test -bench=. -cpuprofile=cpu.prof

$ go tool pprof -http=:8080 cpu.prof

$ go tool pprof cpu.prof
(pprof) web

# 分析内存
$ go test -bench=. -memprofile=heap.prof

二进制程序

gin 框架

gin 框架可以直接使用 gin 官方提供的中间件 gin-contrib/pprof,示例如下:

package main

import (
  "github.com/gin-contrib/pprof"
  "github.com/gin-gonic/gin"
)

func main() {
  router := gin.Default()
  pprof.Register(router)
  router.Run(":8080")
}
  • 使用 pprof 工具查看堆heap profile
go tool pprof http://localhost:8080/debug/pprof/heap
  • 查看 30 秒 CPU profile
go tool pprof http://localhost:8080/debug/pprof/profile
  • 在程序中调用 runtime.SetBlockProfileRate 后,查看 goroutine 的阻塞 blocking profile
go tool pprof http://localhost:8080/debug/pprof/block
  • 收集 5 秒钟的执行跟踪 trace
wget http://localhost:8080/debug/pprof/trace?seconds=5
# 使用 go tool trace 分析

参考

  1. https://github.com/google/pprof
  2. https://go.dev/blog/pprof
  3. https://pkg.go.dev/net/http/pprof
  4. Your pprof is showing
Home Archives Categories Tags Statistics
本文总阅读量 次 本站总访问量 次 本站总访客数