这是我参与「第五届青训营 」伴学笔记创作活动的第 8 天
Go程序性能分析工具
性能调优原则
- 要依靠数据不是猜测
- 要定位最大瓶颈而不是细枝末节
- 不要过早优化
- 不要过度优化
性能分析工具 pprof
- 希望知道应用在什么地方耗费了多少 CPU、Memory
- pprof 是用于可视化和分析性能分析数据的工具
进入 go-pprof-practice 文件夹,执行
go build
./go-pprof-practice
保持程序运行,打开浏览器访问 http://localhost:6060/debug/pprof/
查看 CPU 占用率
这时,使用活动监视器查看,可以看到 CPU 占用相当高,显然是有问题的,用 go tool pprof 来排查一下,新开一个终端,输入
go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10"
输入 top 命令,查看 CPU 占用较高的调用
flat: 当前函数本身的执行耗时
flat%: flat占 CPU 总时间的比例
sum%: 上面每一行 flat% 总和
cum: 指当前函数本身加上其调用函数的总耗时
cum%: cum 占 CPU 总时间的比例
Flat = Cum:函数中不调用其他函数
Flat = 0:函数中只有其他函数的调用
输入 list Eat 查看第一个 .Eat 的文件内容,看看是什么原因导致的
能够发现是没有任何操作的循环导致的
接下来我们可以图形化显示调用栈信息,但是需要事先在机器上安装 graphviz,brew install graphviz。安装完成后,在交互式终端里输入 web,实际上是生成一个.svg文件,打开一个默认浏览器,如果打开的不是浏览器(比如代码编辑器),需要设置一下使用默认浏览器打开。
把无用的循环注释掉,CPU 占用率就降下来了,但是内存占用率还是高居不下。
现在查看内存占用率
我们再次使用 \text{pprof} 命令,
go tool pprof http://localhost:6060/debug/pprof/heap,top 查看花费内存大的。
list Steal 查看消耗内存大的代码。
再使用 web 查看。
把这行内存占用高的注释掉,现在内存也降下来了。
如果使用 go tool pprof -http=:8080 http://localhost:6060/debug/pprof/heap 命令,会弹出可视化 \text{pprof} 网页工具。
访问 \text{top} 和终端里的一样效果,好看一点。
\text{SAMPLE} 中
alloc_objects:程序累计申请的对象数
alloc_space:程序累计申请的内存大小
inuse_objects:程序当前持有的对象数
inuse_space:程序当前占用的内存大小
但是,内存相关的性能问题真的已经全部解决了吗?
切换到累积分配内存的模块,可以看到还有代码也占用了很多内存。
每次申请来,它也没有用,在之前是看不出来的。现在把这行注释掉。
goroutine - 协程
go tool pprof -http=:8080 http://localhost:6060/debug/pprof/goroutine
\text{View} 中的 Flame Graph
- 从上到下表示调用顺序
- 每一块代表一个函数,越长代表 CPU 的时间更长
- 火焰图是动态的,支持点击块进行分析
web浏览器支持搜索,在 Source 时图下搜索 wolf,wolf 是占用了次数最多的协程。
把相关代码注释掉
mutex - 锁
go tool pprof -http=:8080 http://localhost:6060/debug/pprof/block
\text{View} 中的 Source 定位到目标代码
把相关代码注释掉
block - 阻塞
做法和前面相同