go性能优化分析工具-pprof

124 阅读4分钟

1 性能分析工具pprof简介

image.png 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

image.png 选择对应版本进行安装即可。(配置好环境变量)

2.2 下载开源代码到本地

github.com/wolfogre/go…

3 pprof性能调优实战

首先本地启动项目,然后打开网址/debug/pprof/

image.png

3.1 CPU

在终端输入命令:go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10" 使用go tool pprof 来采集10秒cpu数据来排查问题(这里需要等待一段时间)

image.png 显示该界面后 输入指令 top

image.png 不同字段表示的含义如下:

类型描述
flat当前函数本身的执行耗时
flat%flat占cpu总时间的比例
sum%上面每一行的flat%的总和
cum当前函数加上其周期函数的总耗时
cum%cum占cpu总时间的比例
通过提示可以看出Eat方法cpu占用过高,输入指令: list Eat 检查代码的具体位置

image.png 找到代码的具体问题是由于函数内执行了多次循环所导致的,到这里已经找到问题所在了,在终端输入指令: web,

image.png 而后解决问题,修改eat函数,减少loop的值或者直接注释掉这部分代码都可以。 修改后系统cpu的占有率高的问题就已经修复了

3.2 内存占用过高(heap)

输入以下命令查看内存的占用情况: go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap"

image.png 这里已经可以看到是哪些函数分配了大量的内存,也可以在顶部的菜单栏选择view目录下的source

image.png 选择之后就可以清楚的看到源码,到底是哪里分配了大量的内存

image.png 在顶部的SAMPLE目录下有四个选项如下

image.png含义分别为:

类型含义
alloc_objects程序累计申请的对象数
alloc_space程序累计申请的内存大小
inuse_objects程序当前持有的对象数
inuse_space程序当前占有的内存大小
这里修改掉内存分配异常的问题

3.3 协程(groutine)

image.png 这里发现代码中有115个协程,明显不正常 使用命令查看协程的情况: go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/goroutine"

image.png 可以在view选项中选择Flame Graph 查看

image.png 可以看到

image.png wolf.(*Wolf).Drink.func1 占用了大量的goroutine(86.2%),查看source源码

image.png 这里可以看到Drink方法每次都会起10个协程,每个协程会sleep30秒后退出,而且drink函数被反复调用,所以导致产生大量的协程。这里还是修改掉这部分bug

3.4 Mutex(锁)

检查不合理的锁争用问题(加锁时间太长等)

image.png 这里我们依然使用命令:go tool pprof -http=:8080 http://localhost:6060/debug/pprof/mutex

image.png 查看source源码

image.png 修改bug即可