Go语言pprof实战笔记(中) | 青训营

前言

上期我们简单做了一个排查CPU占用过高的实践,相信小伙伴们已经熟悉了go tool pprof这个工具了,这期我们实验的节奏会更快,要做好几个实验哦

实战开始

老规矩,先把 炸弹程序 运行起来,然后打开任务管理器观察有哪些异常的性能数据。

排查内存占用过高

我们很明显地看到这个程序的占用了 7GB 多的内存,实在是太恐怖啦。

我们要排查的是内存占用过高,理所当然的应该借助 go tool pprof命令来分析 heap 文件。接下来,准备动手,打开命令行输入go tool pprof http://localhost:6060/debug/pprof/heap。很快啊,熟悉的交互式终端就出现了。

首先使用top命令查看到底是哪些方法占用了这么多内存

经过一番仔细的查看,发现原来是
github.com/wolfogre/go-pprof-practice/animal/muridae/mouse.(*Mouse).Pee.func1方法和github.com/wolfogre/go-pprof-practice/animal/muridae/mouse.(*Mouse).Steal方法各自占用了 1.2GB 的内存。

有两处地方都有问题,我们先使用list命令查看Pee方法有什么问题

原来是在Pee方法里面启动了一个goroutine来不断地往一个名叫slowBuffer的二维切片里面追加一维切片。好了,问题找到了,接下来使用list命令查看Steal方法有什么问题。

定睛一看,原来是一样的问题,那么我们先把这两个地方 优化(注释) 掉。

此处省略优化的详细步骤...

在优化后重新启动程序,可以发现 CPU内存 看起来都很正常,没有出现异常的数据,那么问题真的就没有了吗?

排查频繁GC

GC 的全称是 Garbage Collection,翻译过来为垃圾回收,用在计算机领域就被称为内存回收。这是一种自动内存管理的机制,它会自动回收那些被分配但不再被使用的内存。这种机制可以帮助开发者避免很多常见的内存管理错误,例如内存泄漏和野指针等问题。

大家都知道golang是追求高性能的,那么频繁的 GC 肯定会影响程序的性能,这是golang所不允许的。虽然现在 CPU内存 的使用率都没有问题,但是我们还是要排查 GC 的回收情况。

所以我们接下来的排查不是排查哪里占用了大量的内存,而是排查哪里在频繁地申请内存又不用,触发GC,影响程序性能。

正常情况来说,我们是不知道 GC 的情况的,那么我们如何来了解 GC 是否频繁发生呢?答案就是查看 GC 日志。为了能查看 GC 的日志,我们需要设置环境变量set GODEBUG=gctrace=1,这样设置的环境变量只在当前终端窗口有效,能有效防止影响到其他 GO 程序的输出。

接下来在终端输入go-pprof-practice.exe | findstr gc,运行 GO 程序的同时把日志做一次过滤,能有效屏蔽其他日志对我们的干扰。

通过 GC 日志我们发现 GC 差不多每3秒就要发生一次,每次都是申请了16MB 的空间然后被 GC 回收掉了,所以大概率是某个地方申请了16MB 空间然后没有使用,被 GC 回收掉了。

对于问题有了自己初步的判断,接下来就是使用go tool pprof命令来检查实际的问题了。还是原来的步骤,使用top list命令来排查相关的问题,不过这里有个前提,就是需要等待程序运行一会,因为内存的分配和回收的频率都是需要一段时间来统计的。

等待程序运行一段时间后输入go tool pprof http://localhost:6060/debug/pprof/allocs进入交互式终端,然后输入top命令查看内存分配情况

可以看到github.com/wolfogre/go-pprof-practice/animal/canidae/dog.(*Dog).Run方法存在问题,接下来使用list命令查看有问题的代码具体在哪。

我们可以看到在Run方法里面存在这样一行代码_ = make([]byte, 16*constant.Mi),这行代码分配了16MB 内存,但是使用了匿名变量 来忽略返回值,导致这个内存没有被使用,没在使用的空间自然就需要 GC 来回收了。

老规矩,发现问题后注释掉(练习需要,切勿模仿

重新启动后观察一下 GC 日志。很好,没有问题了。

总结

目前用到的命令其实很少也很简单,只需要我们有一双善于发现问题的眼睛,就能使用工具快速定位问题。

好了,还剩几个实践操作我们下期见!

相关推荐
CallBack8 个月前
Typora+PicGo+阿里云OSS搭建个人图床,纵享丝滑!
前端·青训营笔记
Taonce1 年前
站在Android开发者的角度认识MQTT - 源码篇
android·青训营笔记
AB_IN1 年前
打开抖音会发生什么 | 青训营
青训营笔记
monster1231 年前
结营感受(go) | 青训营
青训营笔记
翼同学1 年前
实践记录:使用Bcrypt进行密码安全性保护和验证 | 青训营
青训营笔记
hu1hu_1 年前
Git 的正确使用姿势与最佳实践(1) | 青训营
青训营笔记
星曈1 年前
详解前端框架中的设计模式 | 青训营
青训营笔记
tuxiaobei1 年前
文件上传漏洞 Upload-lab 实践(中)| 青训营
青训营笔记
yibao1 年前
高质量编程与性能调优实战 | 青训营
青训营笔记
小金先生SG1 年前
阿里云对象存储OSS使用| 青训营
青训营笔记