golang性能分析,pprof的使用,graphviz,火焰图

  • Post author:
  • Post category:golang


golang中的pprof的使用,graphviz



一、关于pprof包

go中有

pprof

包来做代码的性能监控,包括

cpu profile, mem profile, block profile

,在两个地方有包:

net/http/pprof
runtime/pprof

其实

net/http/pprof

中只是使用

runtime/pprof

包来进行封装了一下,并在http端口上暴露出来。二者的区别在于:

1、

runtime/pprof

:调用了就开始采样了,数据会不断被写入文件。

2、

net/http/pprof

:只有在调用了某个API的时候,才会发起采样,并sleep一段时间,时间到了就会关闭采样,所以日志文件是按需写入的。



二、使用



方法1、WEB服务器

如果你的go程序是用http包启动的web服务器,你想查看自己的web服务器的状态。这个时候就可以选择

net/http/pprof

。你只需要引入包

_"net/http/pprof"

,然后就可以在浏览器中使用

http://localhost:port/debug/pprof/

直接看到当前web服务的状态,包括CPU占用情况和内存使用情况等。具体使用情况你可以看godoc的说明。



方法2、常驻进程

如果你的go程序不是web服务器,而是一个服务进程,那么你也可以选择使用

net/http/pprof

包,同样引入包

_ "net/http/pprof"

,然后在开启另外一个goroutine来开启端口监听。

比如:

go func() {
        log.Println(http.ListenAndServe(":6060", nil)) 
}()

无论是常驻进程,还是WEb服务器场景,pprof 包都会注册如下路由

func init() {
	http.HandleFunc("/debug/pprof/", Index)
	http.HandleFunc("/debug/pprof/cmdline", Cmdline)
	http.HandleFunc("/debug/pprof/profile", Profile)
	http.HandleFunc("/debug/pprof/symbol", Symbol)
	http.HandleFunc("/debug/pprof/trace", Trace)
}

如果是WEB服务器,我们可以选择监听新的端口,或者使用原有监听;但是如果使用原有监听的话可能无法注册路由,比如你使用的是GIN框架,这个时候可以使用方法2来实现;当然,GIN也有方式来以方法1来开启pprof,这个后面再讲。

访问地址:

http://localhost:6060/debug/pprof/

,或者

http://localhost:6060/debug/pprof?seconds=30


在这里插入图片描述

点击每一项可以看到一些原始数据。

由源码可知,基于 http 的 pprof 是在你请求 profile 的时候,它会临时采集一个时间区间(比如30秒)内的对应性能数据;而访问其他指标会立即返回。再采集的时候需要来个压测,这样才会有数据。

这是一种非侵入式的指标采集,几乎不会影响服务的性能。



方法3、普通程序

如果你的go程序只是一个应用程序,比如计算fabonacci数列,由于程序的执行时间不确定,所以就不好使用

net/http/pprof

包了,最好使用到

runtime/pprof

来手动开启采样。具体做法就是用到

pprof.StartCPUProfile



pprof.StopCPUProfile

。比如下面的例子:

var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")

func main() {
    flag.Parse()
    if *cpuprofile != "" {
        f, err := os.Create(*cpuprofile)
        if err != nil {
            log.Fatal(err)
        }
        pprof.StartCPUProfile(f)
        defer pprof.StopCPUProfile()
    }

运行程序的时候加一个

--cpuprofile

参数,比如

./fabonacci --cpuprofile=fabonacci.prof

这样程序运行的时候的cpu信息就会记录到

fabonacci.prof

中了。记录的是从

pprof.StartCPUProfile



pprof.StopCPUProfile

这期间的CPU的累积使用情况。

由源码可知,当调用了

pprof.StartCPUProfile

,就开始以每秒100次(也就是每10毫秒一次)的频率对CPU的使用情况进行采样,而

pprof.StopCPUProfile

就是将采样频率设置为0且停止采样,然后等待将采样数据写入文件的过程执行完毕,因此必须要保证

pprof.StopCPUProfile

被正常执行完毕,否则可能日志文件没有内容或者内容错误。

查看内存泄漏或消耗分析,可以使用

fm, err := os.OpenFile("./tmp/mem.out", os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
    log.Fatal(err)
}
pprof.WriteHeapProfile(fm)
fm.Close()



三、go tool pprof 与 图形化

通过 pprof 得到的信息都是原始数据,阅读起来很费劲,我们可以通过

go tool pprof

命令来辅助查看以及图形化的方式来展示。

下载安装 graphviz :https://graphviz.org/download/

https://gitlab.com/api/v4/projects/4207231/packages/generic/graphviz-releases/2.47.3/stable_windows_10_cmake_Release_x64_graphviz-install-2.47.3-win64.exe

并且添加到环境变量。

否则会报错:

failed to execute dot. Is Graphviz installed? Error: exec: "dot": executable file not found in %PATH%

示例:

pp.gp

package main

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

func myHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello World!\n")
}

func main() {
	http.HandleFunc("/hello", myHandler)
	log.Fatal(http.ListenAndServe(":6060", nil))
}

以查看CPU性能为例,先启动压测

go-wrk -c=400 -t=8 -n=100000 http://localhost:6060/hello

再输入命令

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

于是进入一个交互界面

在这里插入图片描述

最后一列为函数名称,其他各项内容意义如下:

flat: 当前函数占用CPU的时间
flat%: 当前函数占用CPU百分比
sum%: 当前所有函数累加使用 CPU 的比例
cum: 当前函数以及子函数占用CPU的时间
cum%:  当前函数以及子函数占用CPU的百分比

由提示可知,它是先将下载的原始数据保存在临时文件,然后再来分析。

常用的两个命令

top 10 列出前10
web   调用 graphviz 生成svg图片,然后打开
list  查看具体的函数分析
pdf   命令可以生成可视化的pdf文件
help  命令可以提供所有pprof支持的命令说明

当输入 web 后,会生成svg文件,会打开浏览器。

在这里插入图片描述

方框里面有百分比,同时方框越大占的CPU时间越多。当然,这样太难分析了,还有更直观的方式。

输入

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

Fetching profile over HTTP from http://localhost:6060/debug/pprof/profile
Saved profile in C:\Users\Administrator.DESKTOP-TPJL4TC\pprof\pprof.samples.cpu.001.pb.gz
Type: cpu
Time: Jul 14, 2021 at 10:53am (CST)
Duration: 30s, Total samples = 23.51s (78.36%)
Entering interactive mode (type "help" for commands, "o" for options)

退出命令行,复制

Saved profile

后面的文件名

go tool pprof -http localhost:3001 C:\Users\Administrator.DESKTOP-TPJL4TC\pprof\pprof.samples.cpu.001.pb.gz

这样就是在浏览器中打开了。

默认是以 greph 的方法展示,首页和上面的图形一样。

可以切换到火焰图 Flame Graph

在这里插入图片描述

每个方块代表一个函数,它下面一层表示这个函数会调用哪些函数,方块的大小代表了占用 CPU 使用的长短。火焰图的配色并没有特殊的意义,默认的红、黄配色是为了更像火焰而已。

另外,有时候我们通过其他途径得到了 pprof 文件,也可以通过它来分析

使用

go tool pprof 应用程序 应用程序的prof文件

或者

go tool pprof prof文件


在这里插入图片描述

go tool pprof 教程:https://github.com/hyper0x/go_command_tutorial/blob/master/0.12.md



版权声明:本文为raoxiaoya原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。