Go程序性能分析工具 | 青训营笔记

78 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 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 的文件内容,看看是什么原因导致的

能够发现是没有任何操作的循环导致的

接下来我们可以图形化显示调用栈信息,但是需要事先在机器上安装 graphvizbrew install graphviz。安装完成后,在交互式终端里输入 web,实际上是生成一个.svg文件,打开一个默认浏览器,如果打开的不是浏览器(比如代码编辑器),需要设置一下使用默认浏览器打开。

把无用的循环注释掉,CPU 占用率就降下来了,但是内存占用率还是高居不下。

现在查看内存占用率

我们再次使用 \text{pprof} 命令,

go tool pprof http://localhost:6060/debug/pprof/heaptop 查看花费内存大的。

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 - 阻塞

做法和前面相同