您的位置 首页 golang

pprof 的使用


基本介绍

pprof 是在做性能优化前的性能分析工具。

安装: go get -u github.com/google/pprof

两个工具

  • 服务型应用 _ "net/http/pprof" 包,专用于采集 web 服务 运行数据的分析
  • 工具型应用 "runtime/pprof" 包,专用于采集 应用程序 运行数据的分析

另外 go tool pprof 是命令行指令,用于获取和分析 Profiling 数据,源数据可以是 http 地址,也可以是本地 Profile 文件;查看模式可以命令行交互模式,也可以是 http 模式(-http 参数)。

服务型应用 (net/http/pprof)

特点是服务要一直运行。比如 web 应用,一边提供 HTTP 服务一边进行分析。

如果使用了默认的 http.DefaultServeMux (http.ListenAndServe("0.0.0.0:8000", nil)),则只需要导入包则可以使用。

如果自定义的 mux,需要手动注册路由规则,如 r.HandleFunc("/debug/pprof/", pprof.Index)

工具性应用 (runtime/pprof)

特点:应用运行一段时间就结束。

应用退出时,把 profile 文件保存到报告文件中。

封装了接口可以调用,如要进行 CPU Profiling,则调用 pprof.StartCPUProfile(w io.Writer) 写入到 w 中,停止时调用 StopCPUProfile();要获取内存数据,直接使用 pprof.WriteHeapProfile(w io.Writer) 函数则可。

可以做?

可以做( $host/debug/pprof/$type, $type 即下方列表的英文单词):

  • CPU 分析(profile): 你可以在 url 上用 seconds 参数指定抽样持续时间(默认 30s),你获取到概览文件后可以用 go tool pprof 命令调查这个概览
  • 内存分配(allocs): 所有内存分配的抽样
  • 阻塞(block): 堆栈跟踪导致阻塞的同步原语
  • 命令行调用(cmdline): 命令行调用的程序
  • goroutine: 当前 goroutine 的堆栈信息
  • 堆(heap): 当前活动对象内存分配的抽样,完全也可以指定 gc 参数在对堆取样前执行 GC
  • 互斥锁(mutex): 堆栈跟踪竞争状态互斥锁的持有者
  • 系统线程的创建(threadcreate): 堆栈跟踪系统新线程的创建
  • trace: 追踪当前程序的执行状况. 你可以用 seconds 参数指定抽样持续时间. 你获取到 trace 概览后可以用 go tool pprof 命令调查这个 trace

基本使用

(由于初学资料的限制,以下暂时均以 net/http/pprof 使用为例)

  1. 编写 Demo 文件 demo.go,运行这个文件
package mainimport (    "log"    "net/http"    _ "net/http/pprof")func main() {    go func() {        for {            log.Println(Add("Hello world"))        }    }()    http.ListenAndServe("0.0.0.0:6060", nil)}var datas []stringfunc Add(str string) string {    data := []byte(str)    sData := string(data)    datas = append(datas, sData)    return sData}

通过 Web 页面分析

  • 访问 http://localhost:6060/debug/pprof/ 页面,可以看到总览
  • 点击其中的链接,可以看到各部分的概览

注:网页点击一些链接会下载文件,这些文件应该是需要专用工具才能打开查看分析,如 profile;而且默认采样时长 30s

通过命令行分析

  • 执行命令 go tool pprof http://localhost:6060/debug/pprof/profile?seconds=60 进行 60s 内进行采样(时间自定,默认 30s)。

  • 此时输出一些信息并已经进入到 交互模式

    $ go tool pprof http://localhost:6060/debug/pprof/profileFetching profile over HTTP from http://localhost:6060/debug/pprof/profileSaved profile in C:\Users\c30004139\pprof\pprof.samples.cpu.003.pb.gzType: cpuTime: Jun 17, 2020 at 3:25pm (CST)Duration: 30.14s, Total samples = 31.64s (104.96%)Entering interactive mode (type "help" for commands, "o" for options)(pprof)

    由输出信息可知:

    • 将 profile 文件保存的位置
    • 分析的 type 是 CPU
    • 采样持续时间(Duration)
    • 提示可以输入 help 查看可用命令,输入 o 查看可用选项
  • 输入 help 显示了所有可用命令和选项

    (pprof) helpCommands:    callgrind        Outputs a graph in callgrind format    comments         Output all profile comments    disasm           Output assembly listings annotated with samples    dot              Outputs a graph in DOT format    eog              Visualize graph through eog    evince           Visualize graph through evince    gif              Outputs a graph image in GIF format    gv               Visualize graph through gv    kcachegrind      Visualize report in KCachegrind    list             Output annotated source for functions matching regexp    pdf              Outputs a graph in PDF format    peek             Output callers/callees of functions matching regexp    png              Outputs a graph image in PNG format    proto            Outputs the profile in compressed protobuf format    ps               Outputs a graph in PS format    raw              Outputs a text representation of the raw profile    svg              Outputs a graph in SVG format    tags             Outputs all tags in the profile    text             Outputs top entries in text form    top              Outputs top entries in text form    topproto         Outputs top entries in compressed protobuf format    traces           Outputs all profile samples in text form    tree             Outputs a text rendering of call graph    web              Visualize graph through web browser    weblist          Display annotated source in a web browser    o/options        List options and their current values    quit/exit/^D     Exit pprofOptions:    call_tree        Create a context-sensitive call tree    compact_labels   Show minimal headers    divide_by        Ratio to divide all samples before visualization    drop_negative    Ignore negative differences    edgefraction     Hide edges below <f>*total    focus            Restricts to samples going through a node matching regexp    hide             Skips nodes matching regexp    ignore           Skips paths going through any nodes matching regexp    mean             Average sample value over first value (count)    nodecount        Max number of nodes to show    nodefraction     Hide nodes below <f>*total    noinlines        Ignore inlines.    normalize        Scales profile based on the base profile.    output           Output filename for file-based outputs    prune_from       Drops any functions below the matched frame.    relative_percentages Show percentages relative to focused subgraph    sample_index     Sample value to report (0-based index or name)    show             Only show nodes matching regexp    show_from        Drops functions above the highest matched frame.    source_path      Search path for source files    tagfocus         Restricts to samples with tags in range or matched by regexp    taghide          Skip tags matching this regexp    tagignore        Discard samples with tags in range or matched by regexp    tagshow          Only consider tags matching this regexp    trim             Honor nodefraction/edgefraction/nodecount defaults    trim_path        Path to trim from source paths before search    unit             Measurement units to displayOption groups (only set one per group):    cumulative    cum              Sort entries based on cumulative weight    flat             Sort entries based on own weight    granularity    addresses        Aggregate at the address level.    filefunctions    Aggregate at the function level.    files            Aggregate at the file level.    functions        Aggregate at the function level.    lines            Aggregate at the source code line level.:   Clear focus/ignore/hide/tagfocus/tagignoretype "help <cmd|option>" for more information(pprof)

几个命令介绍:

  • list,
  • dis

CPU profile 的 top 命令

在 CPU profile 交互页面输入 topN 可以查看 top N 的概况(N 可省略,默认为 10)

(pprof) topShowing nodes accounting for 29.92s, 94.56% of 31.64s totalDropped 117 nodes (cum <= 0.16s)Showing top 10 nodes out of 33      flat  flat%   sum%        cum   cum%    28.52s 90.14% 90.14%     28.58s 90.33%  runtime.cgocall     0.81s  2.56% 92.70%      0.82s  2.59%  runtime.stdcall1     0.24s  0.76% 93.46%      0.25s  0.79%  runtime.stdcall3     0.16s  0.51% 93.96%     29.10s 91.97%  internal/poll.(*FD).writeConsole     0.05s  0.16% 94.12%     29.28s 92.54%  internal/poll.(*FD).Write     0.04s  0.13% 94.25%      0.18s  0.57%  runtime.findrunnable     0.03s 0.095% 94.34%      0.18s  0.57%  runtime.mallocgc     0.03s 0.095% 94.44%      0.25s  0.79%  runtime.mcall     0.02s 0.063% 94.50%     29.49s 93.20%  log.(*Logger).Output     0.02s 0.063% 94.56%     29.71s 93.90%  log.Println(pprof)

信息:

  • 显示的节点在总共 31.64s 的抽样中,占 29.92s,比例 94.56%
  • 在 33 个样本中显示了 top 10
  • 列表解释(cum: cumulative 堆积的)
    • flat: 在给定函数上运行耗时
    • flat%: 在给定函数上运行耗时总比例
    • sum%: 给定函数 累计 使用 CPU 总比例
    • cum: 当前函数 以及包含子函数 的调用运行总耗时
    • cum%: 同上的 CPU 运行耗时总比例
    • 最后一列为函数名称

作者:EDDYCJY
链接:https://www.jianshu.com/p/4e4ff6be6af9
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

heap profile 的 top 命令

go tool pprof http://localhost:6060/debug/pprof/heap

$ go tool pprof http://localhost:6060/debug/pprof/heapFetching profile over HTTP from http://localhost:6060/debug/pprof/heapSaved profile in C:\Users\c30004139\pprof\pprof.alloc_objects.alloc_space.inuse_objects.inuse_space.001.pb.gzType: inuse_spaceTime: Jun 17, 2020 at 3:52pm (CST)Entering interactive mode (type "help" for commands, "o" for options)(pprof)(pprof) topShowing nodes accounting for 10.04GB, 100% of 10.04GB total      flat  flat%   sum%        cum   cum%   10.04GB   100%   100%    10.04GB   100%  main.Add         0     0%   100%    10.04GB   100%  main.main.func1(pprof)
  • inuse_space: 常驻内存占用情况
  • alloc_objects: 内存临时分配情况

可视化界面

编写 test 用例,demo_test.go:

package mainimport "testing"const url = "hello world"func TestAdd(t *testing.T) {    s := Add(url)    if s == "" {        t.Errorf("Test.Add error")    }}func BenchmarkAdd(b *testing.B) {    for i := 0; i < b.N; i++ {        Add(url)    }}

执行测试 go test -bench=. -cpuprofile=cpu.prof 及输出:

$ go test -bench=. -cpuprofile=cpu.profgoos: windowsgoarch: amd64pkg: awesomeProject/pprofBenchmarkAdd-12         13364784                88.3 ns/opPASSok      awesomeProject/pprof    1.828s

参数解释:

  • -bench: 通过 go help testflag 查看,按通配运行 benchmarks
  • -cpuprofile: 指定 CPU profiling 的保存文件
  • -memprofile: 指定 Memory profiling 的保存文件

结果在本目录生成了 cpu.prof 文件

启用可视化界面

需要安装 graphviz,参考:Graphviz安装及简单使用

  • 方式一: go tool pprof -http=:8080 cpu.prof
  • 方式二: go tool pprof cpu.prof,然后在交互页面输入 web [funcName] 命令(函数调用图生成 svg 文件并用浏览器查看)
graphviz-pprof
  • Top, 与前面介绍的几个列一样
  • Graph, 函数调用图,线框越大越粗表明占用时间越多
  • Flame Graph, 火焰图
  • Peek, 在 Top 的基础上显示了调用的上下文文件
  • Source, 看到了源码,及源码处执行时间
  • Disassemble

火焰图🔥

火焰图,调用顺序是从上到下(有些是从下到上,如火焰一般),每一块代表一个函数,越大代表占用 CPU 时间越长。

点击块深入分析。

刨析火焰图,参考如何读懂火焰图?

  • 火焰图是对系统调用栈进行抽样调查
  • 一般采样记录信息有三个参数:采样的进程号、采样的频率(每秒采样多少次,通常 99 次)、采样持续时间
  • 如,对某 一个进程调用栈 进行采样,每秒 99 次(Hz)、持续 30s。如果这个服务器有 16 个 CPU,就能采集到 99 * 30 * 16 = 47520 个调用栈信息
  • 将调用栈信息组装成火焰图
  • 火焰图 Y 轴表示调用栈,每一个 都是一个函数。调用栈越深,火焰越高。火焰顶端是正在执行的函数,底端是父函数(有些火焰是正的,有些是倒的)
  • 火焰图 X 轴表示抽样次数。如果一个函数越宽,就表示被抽到的次数越多,执行时间越长。
  • 注意:X 轴不表示时间先后顺序,而是所有调用栈合并后,按字母顺序排列的。
  • 火焰图的颜色表示 CPU 的繁忙程度。
  • 火焰图就是看顶层那个函数最宽。若有“平顶”(plateaus),就很有可能存在性能问题。
  • 火焰图是 SVG 图(Scalable Vector Graphics 可伸缩的矢量图形参考),可以很方便得进行互动。

火焰图局限:

  • 调用栈过深时,某些系统只返回前面一部分(如前 10 层)
  • 函数名缺失时,只能用内存地址来表示(如匿名函数)

参考


文章来源:智云一二三科技

文章标题:pprof 的使用

文章地址:https://www.zhihuclub.com/7211.shtml

关于作者: 智云科技

热门文章

发表评论

您的电子邮箱地址不会被公开。

网站地图