Go程序的性能分析整体可以分为两步:
- 生成性能数据文件
- 对性能数据文件进行分析
生成性能数据文件
性能数据文件的生成有三种方式。
通过命令行生成性能数据文件
可以在go test
进行性能测试的时候生成性能数据文件,因为我们关注cpu和内存数据,所以我们添加参数来生成这两者的数据文件。
例如
$ go test -bench=".*" -cpuprofile cpu.profile -memprofile mem.profile
执行上述命令会生成3个文件:
- v1.test:测试生成的二进制文件,在性能分析的时候解析各种符号。
- cpu.profile:cpu性能数据文件
- mem.profile:内存性能数据文件
通过代码来生成性能数据文件
利用runtime/pprof
包,编写代码生成性能数据文件。
package main
import (
"os"
"runtime/pprof"
)
func main() {
// 生成cpu性能数据文件
cpuOut, _ := os.Create("cpu.out")
defer cpuOut.Close()
pprof.StartCPUProfile(cpuOut)
defer pprof.StopCPUProfile()
// 生成内存性能数据文件
memOut, _ := os.Create("mem.out")
defer memOut.Close()
defer pprof.WriteHeapProfile(memOut)
Sum(3, 5)
}
func Sum(a, b int) int {
return a + b
}
运行之后就会在当前目录生成cpu.profile和mem.profile数据文件。
通过net/http/pprof生成性能数据文件
对于http server,如何使用的是net/http
包的默认ServerMux,那么直接匿名导入包即可。
import _ "net/http/pprof"
因为在包下存在init函数注册了对应的handler
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)
}
如果使用的不是默认的ServerMux,或者使用的不是官方的net/http
包的话,只需要按照上面init函数的形式,将这几个handler进行封装注册路由即可。
然后启动http服务,访问对应的路由即可收集到数据。
执行
$ curl http://127.0.0.1:8080/debug/pprof/profile -o cpu.profile
访问/debug/pprof/profile路由,pprof就会采集这30s内的cpu性能数据,生成cpu.profile数据文件。
同样的,生成内存性能数据文件可以执行下面的命令
$ curl http://127.0.0.1:8080/debug/pprof/heap -o mem.profile
具体的ip和端口根据实际启动的服务为准。
性能分析
在进行性能分析时,我们可以采取不同的手段来分析性能,比如分析采样图、分析火焰图,还可以使用go tool pprof交互模式来查看函数CPU和内存消耗数据。
cpu性能分析
默认情况下,Go语言的运行时会以100Hz(每秒100次,每10ms一次)的频率对CPU使用情况进行采样。每次采样,会记录正在运行的函数,并统计其运行时间,从而生成CPU性能数据。
分析采样图
首先,确保系统安装了graphviz
$ sudo yum -y install graphviz.x86_64
然后,执行go tool pprof生成调用图,可以生成不同格式的图片
$ go tool pprof -svg cpu.profile > cpu.svg # svg 格式
$ go tool pprof -pdf cpu.profile > cpu.pdf # pdf 格式
$ go tool pprof -png cpu.profile > cpu.png # png 格式
图片中的有向线段标识调用关系,由没有箭头的一端调用有箭头的一端。而线段上的数字就是采样周期内调用这个函数的耗时。
矩形方框内则包含如下数据
- 函数名/方法名。包括包名、结构体名、函数名/方法名,方便快速定位到函数/方法。
- 本地采样时间,以及在采样总数中所占比例。本地采样时间时指采样点落在该函数中的总时间。
- 累积采样时间,以及在采样总数中所占比例。累积采样时间是指采样点落在该函数,以及被它直接或者间接调用的函数中的总时间。
累积采样时间越长,矩形就越大,但是这并不意味着这个函数本身有问题,可能是其调用的函数存在问题。不过本地采样时间很大,那么就是这个函数本身有问题了。
无论如果,大矩形都是值得我们关注的地方。
分析火焰图
火焰图可以更加直观地让我们观察到性能瓶颈。
go tool pprof提供的-http参数,可以使我们通过浏览器浏览采样图和火焰图,执行如下命令
$ go tool pprof -http="0.0.0.0:8081" v1.test cpu.profile
就可以访问命令中的地址在浏览器中查看数据了。
ui界面提供了不同的采样数据视图,火焰图选择Flame Graph。火焰图有如下特征:
- 每一列代表一个调用栈,每个格式代表一个函数。
- 纵轴展示了栈的深度,调用关系按照从上到下排列。最下面的格子代表采样时,正在占用CPU的函数。
- 调用栈在横向会按照字母排序,并且相同的调用栈会合并,所以一个格子的宽度越大,说明这个函数越可能时瓶颈。
查看火焰图时,重点关注的就是横向越宽的格子。
用go tool pprof交互模式查看数据
执行如下命令可以进行交互模式来查看性能数据
$ go tool pprof v1.test cpu.profile
File: v1.test
Type: cpu
Time: Aug 17, 2021 at 2:17pm (CST)
Duration: 56.48s, Total samples = 440ms ( 0.78%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof)
可以数据指令来查看想要的数据,不过这里就进行过多的介绍了,还是更加推荐火焰图的方式,要更加直观一些。
内存性能分析
内存性能分析与cpu性能分析的方法比较类似,将前面的cpu性能文件替换为内存数据文件即可。
标签:分析,profile,数据文件,pprof,性能,采样,cpu From: https://www.cnblogs.com/smarticen/p/17077154.html