go 性能监控神器--pprof

72 阅读7分钟

pprof简介

pprof是go自身提供的工具链,可以用来做性能监控。pprof有两个包:

  • runtime/pprof
    pprof的具体实现,所有类型的代码都可以使用。如果不是Web应用程序,建议使用该包。

  • net/http/pprof
    对runtime/pprof包进行简单封装,并在http端口上暴露出来。适合Web应用程序使用。

pprof监控内容

pprof监控的内容项目入下表所示。

类型描述备注
allocs内存分配情况的采样信息可以用浏览器打开,但可读性不高
blocks阻塞操作情况的采样信息可以用浏览器打开,但可读性不高
cmdline显示程序启动命令及参数可以用浏览器打开,但可读性不高
goroutine当前所有协程的堆栈信息可以用浏览器打开,但可读性不高
heap堆上内存使用情况的采样信息可以用浏览器打开,但可读性不高
mutex锁争用情况的采样信息可以用浏览器打开,但可读性不高
profileCPU 占用情况的采样信息浏览器打开会下载文件
threadcreate系统线程创建情况的采样信息可以用浏览器打开,但可读性不高
trace程序运行跟踪信息浏览器打开会下载文件

使用pprof进行监控

一下两种使用pprof进行性能监控的方式只能生成监控信息文件,具体的分析需要使用go tool pprof [binary] file进行查看和分析。

非Web应用程序

非Web应用程序使用包runtime/pprof,生成监控文件。

下面示例进行CPU监控,并将监控数据存放在当前项目的pprof/profile_file/profile_file文件中。

import (
"log"
"os"
"path/filepath"
"runtime/pprof"
)
// 进行CPU监控
func CreateProfileFile() {
    dir, err := os.Getwd()
if err != nil {
        log.Fatalln("get current directory failed.", err)
    }

    fileName := filepath.Join(dir, "pprof", "profile_file", "profile_file")
    f, _ := os.Create(fileName)
// start to record CPU profile and write to file `f`
    _ = pprof.StartCPUProfile(f)
// stop to record CPU profile
defer pprof.StopCPUProfile()
// TODO do something
}
👉点击领取Go后端开发资料合集Web应用程序

Web应用程序使用包net/http/pprof,可以搭建Web服务器查看监控信息。通过http://locahost:6060/debug/pprof进行查看相关的监控信息文件。

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

func main() {
    log.SetFlags(log.Lshortfile | log.LstdFlags)
    log.SetOutput(os.Stdout)

    runtime.GOMAXPROCS(1)
    runtime.SetMutexProfileFraction(1)
    runtime.SetBlockProfileRate(1)

go func() {
if err := http.ListenAndServe(":6060", nil); err != nil {
            log.Fatal(err)
        }
        os.Exit(0)
    }()

注意

如果你使用自定义的 Mux,则需要手动注册一些路由规则:

mux.HandleFunc("/debug/pprof/", pprof.Index)
mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
mux.HandleFunc("/debug/pprof/trace", pprof.Trace)

pprof监控信息使用

golang原生自带pprof工具的go tool pprof [binary] file命令进入交互式终端来排查应用程序的性能问题。其中,

  • binary
    正在执行的二进制可执行程序,可选。

  • file
    pprof监控生成的文件。可以是具体的文件如profile.pprof,也可以是web站点的地址,如http://localhost:6060/debug/pprof/profile。
    进入终端之后,排查性能问题的三个命令为:

  • top
    查看资源较高的调用。

  • list
    list 代码片段查看问题代码具体位置。

  • web
    在Web Browser上图形化显示当前的资源监控内容。需要事先安装graphviz。
    web命令的实际行为是产生一个 .svg文件,并调用系统里设置的默认打开 .svg 的程序打开它。如果系统里打开 .svg 的默认程序并不是浏览器(比如代码编辑器),需要设置一下默认使用浏览器打开 .svg 文件。然后浏览器自动打开,可以看到:

image.pngwx_fmt=other&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1)

示例 block的监控信息

如果需要其他命令,可以在pprof交互式终端里输入help查看其他命令的使用方法。例如,

  • svg
    生成svg图。

  • pdf
    生成pdf文件,显示svg图。

  • png
    生成png图片,显示svg图。

  • ...
    当然还有很多其他的命令和选项,请自行学习验证。

pprof监控信息展示——火焰图

火焰图(Flame Graph)是 Bredan Gregg 创建的一种性能分析图表,因为它的样子近似火焰而得名。golang性能监控结果可以转换成火焰图来进行直观展示。火焰图 svg 文件可以通过浏览器打开,它展示调用图的最大优点是火焰图动态的——可以通过点击每个方块来分析它上层概况/下层详细的内容。

火焰图的调用顺序从下到上,每个方块代表一个函数,它上面一层表示这个函数会调用哪些函数,方块的大小代表了占用资源值的多少(例如,CPU使用时间的长短,内存使用的大小等)。火焰图的配色并没有特殊的意义,默认的红、黄配色是为了更像火焰而已。

生成火焰图,有两种方式:go-torch(golang version < 1.10)和golang原生的pprof(golang version < 1.10+的pprof集成了火焰图功能)。

go-torch

go-torch是uber 开源的一个工具。go-torch可以直接读取 golang 的监控数据文件,并生成一个火焰图的 svg 文件。

go-torch工具使用非常简单,最简单的是使用go-torch的docker镜像运行,无需安装go-torch。

  1. 首先进行docker安装(ubuntu)。其他操作系统的安装参考codker安装。

  2. 运行go-rorch镜像 uber/go-torch 。
    如果不知道相关命令,可以执行$ sudo docker run uber/go-torch -h查看go-torch的使用帮助。

$ sudo docker run uber/go-torch -h
Usage:
  go-torch [options] [binary] <profile source>

pprof Options:
  -u, --url=         Base URL of your Go program (default:
                     http://localhost:8080)
      --suffix=      URL path of pprof profile (default: /debug/pprof/profile)
  -b, --binaryinput= File path of previously saved binary profile. (binary
                     profile is anything accepted by
                     https://golang.org/cmd/pprof)
      --binaryname=  File path of the binary that the binaryinput is for, used
for pprof inputs
  -t, --seconds=     Number of seconds to profile for (default: 30)
      --pprofArgs=   Extra arguments for pprof

Output Options:
  -f, --file=        Output file name (must be .svg) (default: torch.svg)
  -p, --print        Print the generated svg to stdout instead of writing to
                     file
  -r, --raw          Print the raw call graph output to stdout instead of
                     creating a flame graph; use with Brendan Gregg's flame
                     graph perl script (see
                     https://github.com/brendangregg/FlameGraph)
      --title=       Graph title to display in the output file (default: Flame
Graph)
      --width=       Generated graph width (default: 1200)
      --hash         Colors are keyed by function name hash
      --colors=      set color palette. choices are: hot (default), mem, io,
                     wakeup, chain, java, js, perl, red, green, blue, aqua,
                     yellow, purple, orange
      --cp           Use consistent palette (palette.map)
      --reverse      Generate stack-reversed flame graph
      --inverted     icicle graph

Help Options:
  -h, --help         Show this help message

最重要的命令有五个:

可选参数选项描述默认值备注
-u, --url=golang代码的基础URL——[scheme]://[host]:[port]http://localhost:8080
--suffix=pprof profile文件URL路径/debug/pprof/profile
-t, --seconds=执行profile的时间长度,单位是秒30
-f, --file=输出文件的名称torch.svg文件扩展名必须是 .svg
-p, --print将生成的svg文件打印到标准输出,而不是写入文件

所有参数都是可选参数。如果没有任何参数,默认情况下,会尝试从http://localhost:8080/debug/pprof/profile 获取监控数据。

例如,从服务器http://10.0.2.15:6060/debug/pprof/block获取阻塞信息,并将生成的svg文件打印到标准输出中,然后信息重定向保存到本地torch.svg文件。

sudo docker run uber/go-torch -u http://10.0.2.15:6060 --suffix=/debug/pprof/block -p > torch.svg
INFO[02:33:36] Run pprof command: go tool pprof -raw -seconds 30 http://10.0.2.15:6060/debug/pprof/block
INFO[02:33:36] Printing svg to stdout

第一次执行由于需要安装go-torch相关依赖和镜像,等待时间较长。

执行成功之后,本地会生成一个torch.svg文件。右键通过浏览器打开,可以看到火焰图,如下图所示:

image.png

go-torch生成火焰图示例

使用go-torch的docker镜像可以在windows操作系统使用。

注:当然了,可以将go-torch和FlameGraph工具分别安装,然后执行go-torch命令。具体参数和go-torch镜像执行-h显示的参数相同。此处不再赘述。

使用golang的pprof查看火焰图

使用go tool pprof可以在Web界面上查看所有类型的资源监控图。
例如,使用pprof查看Web服务器的阻塞监控数据,并将结果展示在6061端口。通过http://localhost:6062/ui/flamegraph即可查看生成的火焰图。

$ go tool pprof -http=:6061 http://localhost:6060/debug/pprof/block
Fetching profile over HTTP from http://localhost:6060/debug/pprof/block
Saved profile in /home/jerry/pprof/pprof.___go_build_main_go.contentions.delay.005.pb.gz

从执行命令的过程,可以看到pprof工具从

http://localhost:6060/debug/pprof/block获取监控数据,并保存到本地:

/home/jerry/pprof/pprof.___go_build_main_go.contentions.delay.005.pb.gz。

然后对该文件进行分析,并启动一个Web服务器:http://localhost:6061。一般会自动弹出一个浏览器并显示结果——默认显示的是graph。但是可以从第一行的菜单中切换View,选择Flame Graph即可显示火焰图。

image.png

pprof启动的性能分析图形化默认Web页面

image.png pprof启动的性能分析图形化火焰图