1 性能分析工具pprof简介
pprof是golang的内置可视化性能分析工具,性能分析工具 pprof 是一个能够帮助用户分析并定位程序运行时性能瓶颈的工具。pprof 能够捕获和分析 CPU 、 Memory 、 Networx 和 Function 的性能信息,这些信息可以用来了解程序的运行状况并进行优化。
以下是 pprof 的详细介绍:
- 生成火焰图:pprof 可以生成 SVG 或者 PNG 格式的火焰图。火焰图是一个可视化工具,用于分析性能问题。它将性能数据可视化为水平柱状图,每一个柱子代表一个函数,宽度表示执行的时间,高度表示时间复杂度或调用次数。火焰图可以清晰地展示程序的运行情况,帮助用户快速定位性能瓶颈。
- 收集性能数据:pprof 通过向程序中添加代理来收集性能数据。这些代理会捕获程序执行时的性能数据,并将其保存在特定的文件中。然后,用户可以使用 pprof 工具分析这些文件并获得有关程序性能的信息。
- 分析数据:pprof 提供了丰富的命令行选项,可以帮助用户分析性能数据。常用的命令包括 top、goroutine、mutex、heap、callgrind 等。这些命令可以用于分析程序的 CPU 、 Memory 、 Networx 和 Function 的性能。
- 可视化界面:pprof 提供了基于 web 的可视化界面,可以帮助用户更方便地分析和展示性能数据。用户可以通过 http://localhost:6060/debug/pprof/ 访问可视化界面。
- 自定义性能分析:pprof 提供了丰富的自定义选项,可以帮助用户根据具体需求进行性能分析。例如,用户可以通过 go tool pprof 命令自定义分析程序中的某个函数,或者通过配置文件自定义分析选项。
2 准备工作
2.1 pprof依赖安装
先要下载图形化依赖安装 Download | Graphviz
选择对应版本进行安装即可。(配置好环境变量)
2.2 下载开源代码到本地
3 pprof性能调优实战
首先本地启动项目,然后打开网址/debug/pprof/
3.1 CPU
在终端输入命令:go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10" 使用go tool pprof 来采集10秒cpu数据来排查问题(这里需要等待一段时间)
显示该界面后 输入指令 top
不同字段表示的含义如下:
| 类型 | 描述 |
|---|---|
| flat | 当前函数本身的执行耗时 |
| flat% | flat占cpu总时间的比例 |
| sum% | 上面每一行的flat%的总和 |
| cum | 当前函数加上其周期函数的总耗时 |
| cum% | cum占cpu总时间的比例 |
| 通过提示可以看出Eat方法cpu占用过高,输入指令: list Eat 检查代码的具体位置 |
找到代码的具体问题是由于函数内执行了多次循环所导致的,到这里已经找到问题所在了,在终端输入指令: web,
而后解决问题,修改eat函数,减少loop的值或者直接注释掉这部分代码都可以。
修改后系统cpu的占有率高的问题就已经修复了
3.2 内存占用过高(heap)
输入以下命令查看内存的占用情况: go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap"
这里已经可以看到是哪些函数分配了大量的内存,也可以在顶部的菜单栏选择view目录下的source
选择之后就可以清楚的看到源码,到底是哪里分配了大量的内存
在顶部的SAMPLE目录下有四个选项如下
含义分别为:
| 类型 | 含义 |
|---|---|
| alloc_objects | 程序累计申请的对象数 |
| alloc_space | 程序累计申请的内存大小 |
| inuse_objects | 程序当前持有的对象数 |
| inuse_space | 程序当前占有的内存大小 |
| 这里修改掉内存分配异常的问题 |
3.3 协程(groutine)
这里发现代码中有115个协程,明显不正常
使用命令查看协程的情况:
go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/goroutine"
可以在view选项中选择Flame Graph 查看
可以看到
wolf.(*Wolf).Drink.func1 占用了大量的goroutine(86.2%),查看source源码
这里可以看到Drink方法每次都会起10个协程,每个协程会sleep30秒后退出,而且drink函数被反复调用,所以导致产生大量的协程。这里还是修改掉这部分bug
3.4 Mutex(锁)
检查不合理的锁争用问题(加锁时间太长等)
这里我们依然使用命令:go tool pprof -http=:8080 http://localhost:6060/debug/pprof/mutex
查看source源码
修改bug即可