性能调优工具pprof | 青训营笔记
这是我参与「第五届青训营 」伴学笔记创作活动的第 6 天
性能调优原则
- 要依靠数据不是猜测
- 要定位最大瓶颈而非细枝末节
- 不要过早优化
- 不要过度优化
性能分析工具
pprof功能简介
-
工具Tool
- runtime/pprof
- net/http/pprof
-
采样Sample
- CPU
- 堆内存-Heap
- 协程-Goroutine
- 锁-Mutex
- 阻塞-Block
- 线程创建-ThreadCreate
-
展示-View
- Top
- 调用图-Graph
- 火焰图-FlameGraph
- Peek
- 源码-Source
- 反汇编-Disassemble
-
分析Profile
- 网页
- 可视化终端
植入:
在main包中import _ "net/http/pprof"
在main函数中添加
go func() {
if err := http.ListenAndServe(":6060", nil); err != nil {
log.Fatal(err)
}
os.Exit(0)
}()
这样就完成了pprof植入。
项目运行后,在浏览器中打开http://localhost:6060/debug/pprof/即可查看指标
CPU
go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10",将一段时间内的信息汇总输入到文件中。
top
进入pprof中后,输入top命令查看CPU占用最高的函数。终端会展示如下信息:
- Flat,当前函数的占用
- Flat%,Flat占总量的比例
- Sum%,上面所有行的Flat%总和
- Cum,当前函数加上其调用函数的总占用
- Cum%,Cum占总量的比例
list
List命令会根据后面给定的正则表达式查找代码,并按行展示出每一行的占用。
例如,之前排查出来tiger.Eat函数占用CPU非常多,此刻输入list Eat。
web
使调用关系可视化,结果在浏览器中展示。
Heap堆内存
输入go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap"启动pprof
在刚刚排查CPU的过程中,使用的是终端,这里使用可视化页面。通过-http=:8080参数,可以开启pprof自带的web UI,性能指标会以网页的形式呈现。
在网页UI中的VIEW选项中,就可以具体分析各项指标。
打开sample菜单,会发现堆内存实际上提供了四种指标
- 默认inuse_space,只展示当前持有的内存。若有的内存已释放,inuse采样就不会展示了。
- inuse_objects,程序当前持有的对象数
- alloc_space,程序累计申请的内存大小
- alloc_objects,程序累计申请的对象数
goroutine协程
goroutine是很元素泄露的,进而会导致内存泄漏。
输入命令go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/goroutine"
可以查看火焰图。自顶向下展示了各个调用,表示各个函数调用之间的层级关系。每一行中,条形越长代表消耗的资源占比越多。
显然那些又平又长的节点是占用资源多的节点。
mutex锁
输入命令go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/mutex"
block阻塞
输入命令go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/block"
性能调优案例
一些基本概念:
- 服务,能单独部署,承载一定功能的程序
- 依赖,若ServiceA的功能实现依赖ServiceB的响应结果,称为ServiceA依赖ServiceB
- 调用链路:能支持一个接口请求的相关服务集合及其相互之间的依赖关系
- 基础库:公共的工具包、中间件
流程
- 建立服务性能评估手段
- 分析性能数据,定位性能瓶颈
- 重点优化项改造
- 优化效果验证
业务服务常见的性能问题是使用基础组件不规范、日志使用不规范等等。另外常见的性能问题就是高并发场景的优化不足。
性能优化的前提是保证正确性,所以在变动较大的性能优化上线之前,还需要进行正确性验证。