美文网首页Go
golang性能优化之pprof及其火焰图

golang性能优化之pprof及其火焰图

作者: Jerry_1116 | 来源:发表于2020-01-04 12:52 被阅读0次

    1 pprof简介

    golang代码的性能监控使用pprof包来做。pprof有两个包:

    • runtime/pprof
      pprof的具体实现,所有类型的代码都可以使用。如果不是Web应用程序,建议使用该包。
    • net/http/pprof
      runtime/pprof包进行简单封装,并在http端口上暴露出来。适合Web应用程序使用。

    2 pprof监控内容

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

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

    3 使用pprof进行监控

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

    3.1 非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
    }
    

    3.2 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)
    

    4 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 文件。然后浏览器自动打开,可以看到:
      示例 block的监控信息

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

    • svg
      生成svg图。
    • pdf
      生成pdf文件,显示svg图。
    • png
      生成png图片,显示svg图。
    • ...
      当然还有很多其他的命令和选项,请自行学习验证。

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

    火焰图(Flame Graph)是 Bredan Gregg 创建的一种性能分析图表,因为它的样子近似火焰而得名。golang性能监控结果可以转换成火焰图来进行直观展示。火焰图 svg 文件可以通过浏览器打开,它展示调用图的最大优点是火焰图动态的——可以通过点击每个方块来分析它上层概况/下层详细的内容。
    火焰图的调用顺序从下到上,每个方块代表一个函数,它上面一层表示这个函数会调用哪些函数,方块的大小代表了占用资源值的多少(例如,CPU使用时间的长短,内存使用的大小等)。火焰图的配色并没有特殊的意义,默认的红、黄配色是为了更像火焰而已。
    生成火焰图,有两种方式:go-torch(golang version < 1.10)和golang原生的pprof(golang version < 1.10+的pprof集成了火焰图功能)。

    5.1 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文件。右键通过浏览器打开,可以看到火焰图,如下图所示:


    go-torch生成火焰图示例

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

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

    5.2 使用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即可显示火焰图。

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

    参考

    1 golang pprof 实战
    2 Go pprof和火焰图
    3 使用 pprof 和火焰图调试 golang 应用
    4 go pprof详细理解及使用
    5 使用pprof及Go 程序的性能优化

    相关文章

      网友评论

        本文标题:golang性能优化之pprof及其火焰图

        本文链接:https://www.haomeiwen.com/subject/ldpzoctx.html