方向三:性能优化分析工具-pprof | 豆包MarsCode AI 刷题

93 阅读3分钟

搭建运行环境

windows11

使用webUI需安装Graphviz:graphviz.org/download/

项目地址:github.com/wolfogre/go…

使用pprof排查性能问题

0.总览

打开http://localhost:6060/debug/pprof/ 可看到相关参数

image.png

各项指标

  • allocs 采样所有过去的内存分配。
  • block 导致同步原语阻塞的堆栈跟踪。
  • cmdline 当前程序的命令行调用信息。
  • goroutine 当前所有 Goroutine 的堆栈跟踪。使用 debug=2 作为查询参数,可以导出与未恢复的 panic 相同的格式。
  • heap 活动对象内存分配的采样。可以通过 gc 参数在采样堆之前触发一次 GC。
  • mutex 记录当前被争用的互斥锁持有者的堆栈跟踪。
  • profile CPU 性能分析。可以通过 duration 参数指定采样时长(秒)。获取分析文件后,可使用 go tool pprof 命令进行分析。
  • threadcreate 创建新操作系统线程的堆栈跟踪。
  • trace 当前程序执行的运行轨迹。可以通过 duration 参数指定跟踪时长(秒)。获取文件后,可使用 go tool trace 命令进行分析。

1.CPU方面 /profile

go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=10" 

使用上述命令捕获10s内进程的消耗

image.png

使用top以分析各项指标

指标含义:

  • flat 当前函数本身的执行耗时
  • flat% flat 占 CPU 总时间的比例
  • sum% 上面每一行的 flat% 总和
  • cum 指当前函数本身加上其调用函数的总耗时
  • cum% 占 CPU 总时间的比例cum

第一次捕获的top数据 image.png

第二次捕获的top数据 image.png

  • flat == cum
    • 只包含本函数调用
  • flat == 0 && cum != 0
    • 只包含对其他函数的调用

我们可以发现,tiger.(*Tiger).Eat和tiger.(*Tiger).Live消耗cpu资源多

使用list Eat,list Live以匹配相关代码 image.png

image.png 说明live()是函数调用Eat()导致

发现有Eat()中有无用loop,将代码注释,重新编译运行,捕获数据,top展示

image.png 有关Eat(),Live()问题解决

2.内存方面 /heap

执行go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap"

view--top image.png

view--source 类似上面的list xxx image.png

同上面类似,注释相关无用代码后,重新编译运行,捕获数据,top展示

image.png

在sample下有四个选项(如下),可能包含其他的内存问题,解决方法类似

  • alloc_objects:程序累计申请的对象数
  • alloc_space:程序累计申请的内存大小
  • inuse_objects:程序当前持有的对象数
  • inuse_space:程序当前占用的内存大小

3.协程 /goroutine

协程间关系

看火焰图:view--Flame Graph

火焰图的结构和含义

  1. 颜色

    • 火焰图中的颜色没有具体的意义,只是为了区分不同的函数和堆栈。
    • 一般来说,颜色不代表资源消耗或性能问题,仅供视觉分辨。
  2. 宽度

    • 每个矩形的宽度表示该函数消耗的资源比例(如 CPU 时间或内存)。
    • 宽度越大,说明函数消耗的资源越多,越值得关注。
  3. 高度

    • 图的高度表示调用栈的深度。
    • 每一层代表一次函数调用,越往上是越深层的函数调用。
  4. 根节点(底部的 root)

    • 火焰图的底部是程序的起始点(根节点)。
    • 例如图中的 root 是最底层,表示程序的入口点。
  5. 向上的调用栈

    • 每一块矩形是一个函数,函数之间的连接表示调用关系。
    • 上层函数是由下层函数调用的。

image.png

我们可以发现,有两个异常的函数,且time.Sleep占据大宽度(函数消耗的资源比例)

找到相关代码,尝试注释,重新编译运行,捕获数据,火焰图展示

image.png 看上去正常了许多。

4.锁方面 /mutex

解决方法同上,不过多赘述

5.阻塞方面 /block

解决方法同上,不过多赘述

总结

image.png