采集profile数据
开启pprof
做 Profiling 第一步就是怎么获取应用程序的运行情况数据,go 语言提供了 runtime/pprof 和 net/http/pprof 两个库。
服务型应用
如果你的应用是一直运行的,比如web应用,那么可以使用 net/http/pprof 库,它能够提供http服务进行分析
如果http服务使用默认的http.DefaultServeMux,以_
方式直接引入pprof包即可
|
|
如果使用非http.DefaultServeMux来提供http api,需要查阅pprof包的init函数自行注册辅助handler
import _ "net/http/pprof"
背后执行了哪些操作?
pprof包的init函数进行了一系列的路由注册操作,具体的说是通过http.HandleFunc
将一系列辅助handler注册到http.DefaultServeMux上
123456789 //package pproffunc 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)}
此后可以通过http://localhost:8080/debug/pprof/
查看当前服务概况
工具型应用
如果你的应用是一次性的,运行一段时间就结束,那么最好的办法就是在应用退出的时候把profiling报告保存到文件中进行分析。这种情况可以使用runtime/pprof
库
|
|
采集数据
访问http://localhost:8080/debug/pprof/
得到以下内容
阻塞分析是一个很独特的分析,它有点儿类似于 CPU 性能分析,但是它所记录的是 goroutine 等待资源所花的时间。阻塞分析对分析程序并发瓶颈非常有帮助,阻塞性能分析可以显示出什么时候出现了大批的 goroutine 被阻塞了。阻塞性能分析是特殊的分析工具,在排除 CPU 和内存瓶颈前,不应该用它来分析。
gorouine
点击goroutine
查看goroutine详情信息,可以看到目前有4个goroutine正在运行,并且可获得相应的堆栈信息
此时url为xxx/debug/pprof/goroutine?debug=1
|
|
将debug参数设置为2(xxxx/debug/pprof/goroutine?debug=2)查看更为详细的信息
|
|
heap信息(两部分)
通过heap查看内存相关信息,信息分两部分
- 第一部分为通过runtime.MemProfile()获取的runtime.MemProfileRecord记录 —todo:不可理解
- 第二部分打印的是通过runtime.ReadMemStats()读取的runtime.MemStats信息
|
|
profile
采集数据获取cpu profile统计数据(需要等待数十秒)
|
|
获取和分析 Profiling 数据
测试环境中启动服务demo
后,我们使用wrk模拟服务高负载访问情况
|
|
cpu profiling
接着打开http://localhost:8080/debug/pprof/
,点击profile
等待数秒后获得profile文件
最后执行go tool pprof -http=":8081" ./demo profile
,自动弹出profile统计结果页面
统计页面可查看火焰图/调用图/分析信息
demo是服务的二进制执行文件
火焰图
源码
memory profiling
接着打开http://localhost:8080/debug/pprof/heap
获得heap文件
最后执行go tool pprof -http=":8081" ./demo heap
,自动弹出heap统计结果页面
top
Flat: 函数占用的内存量
Flat%: 函数内存使用量占总内存使用量比例
Sum%: 以上几行Flat合计内存使用量占比
Cum: 累计内存使用量(外层=内层使用量总和)
火焰图
Peek