导读:在使用golang进行开发过程中,经常需要对程序进行性能分析和优化,pprof是首选工具。在使用过程中,pprof有多个入口,同时也提供了多维度的执行数据,到底我们该如何去使用这个工具,下面我们来一起学习。
golang在语言层面集成了profile采样工具,在程序运行过程中可以获取cpu、heap、block、traces等执行信息,这些会涉及到runtime/pprof、net/http/pprof、runtime/trace等package。本文中所讲内容均基于go 1.9.2版本。
一般情况下,获取profile数据最有两种形式:web形式与profile文件生成形式。
web形式
通过web形式获取采样数据需要在主函数中添加以下代码:
net/http/pprof包的init函数中注册了以下路由到http服务中:
下面分别说明各个路由对应服务的功能:
debug/pprof/cmdline
这个接口功能很简单,主要是调用os.Args,获取程序启动时的命令及参数。访问http://ip:port/debug/pprof/cmdline 即可获取结果。
debug/pprof/profile
此接口返回CPU的profile,调用了runtime/pprof包的StartCPUProfile,采样频率为100Hz。接口默认是返回30秒的数据,可以通过seconds参数设定需要获取的数据时长。比如获取10秒钟的cpu profile数据,有两种方式进行数据获取与分析:
1.go tool pprof http://ip:port/debug/pprof/profile?seconds=10,然后会进入交互模式,直接就可以查看数据,如下:
2. 先获取profile文件,然后使用go tool pprof进行分析。
wget http://localhost:8080/debug/pprof/profile?seconds=10 -O testfile
然后进行分析:go tool pprof testfile, 如下:
其实第一种方式只是把获取文件和交互操作模式放到一起执行而已,profile数据已经被保存到了/tmp目录下。
debug/pprof/symbol
根据传入的程序计数器(PC)的值,获取对应的函数的名称信息,调用了runtime包的FuncForPC获取对应的函数信息。可以传入多个PC值,以加号作为连接符号,比如访问:http://ip:port/debug/pprof/symbol?0x4e667d+0x6ec770 (PC值当然是每个程序运行都不一样,这里只是个示例),返回PC值与函数对应名称的信息,如下:
num_symbols: 10x4e667d io/ioutil.ReadAll0x6ec770 main.httpGet
debug/pprof/trace
此接口用于获取程序执行中的事件跟踪信息,比如协程、系统调用、GC、堆大小改变等事件,大多数事件的跟踪精确度能达到纳秒级别,后端调用了runtime包的StartTrace,会进行一个STW的操作。获取数据的时长默认为1秒,可以通过seconds参数进行修改。先通过以下命令获取数据:
wget http://ip:port/debug/pprof/trace?seconds=10 -O tracefile
然后执行go tool trace tacefile进行数据分析,如下:
进入View trace可以看到如下信息:
以此可以对执行信息进行深入分析。
debug/pprof/
如果访问此路径时,不包含子路径,返回所有可用类型的profile列表,访问http:/ip:port/debug/pprof,如下:
如果包含子路径,可用获取对应如下子路径对应的详细profile信息:
url后面有一个debug参数,其值可以为0、1或者其他预定的值,对以上5种类型的profile均起作用。debug分别代表以下含义:0,返回压缩后的原始格式的数据,其内容只包含pprof所需要的相关十六进制地址;1,返回内容会包含函数名、行号等信息,方便直接查看信息。除了以上两种情况外,某些类型的profile有其它预定的debug值,比如goroutine类型的profile,debug可以等于2。
下面来看上面五种profile的信息:
block:报告协程阻塞的情况,可以用来分析和查找死锁等性能瓶颈,默认不开启, 需要调用runtime.SetBlockProfileRate开启。下面看个例子,访问http://ip:port/debug/pprof/block?debug=1,其展示结果如下:
可以看出图中的阻塞都发生在网络等待上。还可以通过go tool pprof http://ip:port/debug/pprof/block进入交互模式进行查看。
goroutine:报告协程相关信息,可以用来查看有哪些协程正在运行、有多少协程在运行等。访问http://ip:port/debug/pprof/goroutine?debug=1,如下:
可以看出图中的大量协程都和网络传输有关系。
heap:查看堆相关信息,包括一些GC的信息。访问http://ip:port/debug/pprof/heap?debug=1
上图中包含了堆分配的细节,同时在底部还包含了整个堆的统计信息、GC的统计信息等。同样,也可以使用go tool pprof http://ip:port/debug/pprof/heap进入交互模式进行查看。可以指定以下4个选项,alloc_objects、alloc_space、inuse_objects、inuse_space默认为alloc_space。
mutex: 查看互斥的争用情况,默认不开启, 需要调用需要在程序中调用runtime.SetMutexProfileFraction。
threadcreate:查看线程创建信息
文件生成形式
通过生成profile文件的形式来获取数据,需要在代码中添加如下代码。
然后使用go tool分析文件。或者使用test的功能获取profile文件:go test -cpuprofile cpu.prof -memprofile mem.prof -bench .
当然,除了以上3种形式,用户也可以在程序直接调用runtime中的功能进行profile数据获取,runtime包中提供了相关的接口。如果想进行更深入的研究,可以查看https://blog.golang.org/2011/06/profiling-go-programs.html
参考文档:
https://golang.org/pkg/net/http/pprof/
https://blog.golang.org/profiling-go-programs
https://github.com/golang/go/wiki/Performance
领取专属 10元无门槛券
私享最新 技术干货