高质量编程与性能调优实战—第二部分|青训营笔记

49 阅读4分钟

简介与前言

本文章是高质量编程与性能调优实战的第二部分,主要内容是pprof工具的使用与实战,并对经典案例进行调优。

性能优化、调优原则:

  • 要依靠数据而不是猜测
  • 要定位最大瓶颈而不是细枝末叶
  • 不要过早优化
  • 不要过度优化

工具与项目简介

性能分析工具pprof

pprof是一个性能分析工具,它可以生成类似火焰图、堆栈图、内存分析图等。Go在1.11版本后在它自带的工具集go tool里内置了pprof工具来分析由pprof库生成的数据文件。Go在语言层面集成了profile采样工具,在程序运行过程中可以获取cpu、heap、block、traces等执行信息pprof工具可以帮助开发人员快速定位程序中的性能瓶颈,从而优化程序性能。它支持多种语言,包括Go、C++、Java、Python等。pprof工具可以通过命令行或Web界面进行操作,提供了丰富的可视化选项,方便开发人员查看和分析性能数据。

项目简介

搭建pprof实践项目,这里使用的是github上一个开源项目,这个项目提前埋入了一些炸弹代码,产生可观测的性能问题,运行该项目会占用1CPU核心和超过GB的内存。

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

项目运行

在运行项目中的 main.go 文件后,可以打开web浏览器,在地址栏输入http://localhost:6060/debug/pprof,结果如下图所示

屏幕截图 2023-08-07 203837.jpg

pprof包内调用runtime包中函数以获取各种运行时信息,其包含如下分析指标。

  • allocs: 过去所有内存分配的样本
  • block: 导致同步原语阻塞的堆栈跟踪
  • cmdline: 当前程序的命令行调用,与/proc/中的 cmdline相同
  • goroutine: 当前所有goroutine的堆栈跟踪
  • heap: A活动对象的内存分配的采样。您可以指定gc GET参数以在获取堆样本之前运行GC。
  • mutex: 竞争互斥体持有人的堆栈痕迹
  • profile: CPU配置文件。您可以在秒GET参数中指定持续时间。获取概要文件后,使用go tool pprof命令调查概要文件。
  • threadcreate: 导致创建新OS线程的堆栈跟踪
  • trace: 当前程序执行的痕迹。您可以在秒GET参数中指定持续时间。获取跟踪文件后,请使用go工具trace命令调查跟踪。

CPU占用分析

分析cpu占用时使用pprof的命令行进行分析。
在终端输入命令 go tool pprof "http://localhost:6060/debug/pprof/profile?seconds=50" 一段时间后返回界面。

top

输入top命令,用于查看占用资源最多的函数

屏幕截图 2023-08-07 204230.jpg

  • flat: 当前函数本身的执行耗时
  • flat%flatCPU总时间的比例
  • sum%: 上面每一行的flat%总和
  • cum: 当前函数本身加上其周期函数的总耗时
  • cum%: cumCPU总时间的比例

通过top命令,得出Eat函数占用CPU时间最长,使用list命令定位到代码的具体行。

list

list命令返回结果如图

屏幕截图 2023-08-07 204336.jpg

可以清楚的发现,loop被定义的太大导致该函数执行时间太长,将loop进行修改。

屏幕截图 2023-08-07 204621.jpg

修改后,再次运行

屏幕截图 2023-08-07 204826.jpg

屏幕截图 2023-08-07 204848.jpg

函数占用率与运行时间恢复了正常。

内存占用分析

经过修改后,程序CPU占用过高的问题已经解决,但是内存使用还是很高。

屏幕截图 2023-08-07 204942.jpg

输入web命令输出可视化的内存占用图,发现Mouse的内存占用率最高。

屏幕截图 2023-08-07 205812.jpg

我们可以使用web分析,而不是使用命令行提高效率。 输入命令go tool pprof -http=:8080 "http://localhost:6060/debug/pprof/heap"
下图与list命令结果相同

屏幕截图 2023-08-07 205840.jpg

点击source可以查看占用最多的代码,并进行修改。

屏幕截图 2023-08-07 205943.jpg

在这里我首先采用了注释的方法,发现程序无法正常运行,在constant中定义类常量Mi为1024*1024,将其改为Ki即可。最终减少了内存的占用。

屏幕截图 2023-08-07 210332.jpg

屏幕截图 2023-08-07 212134.jpg