这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记。
pprof 是 Go 语言中分析程序运行性能的工具,它能提供各种性能数据:
| 类型 | 描述 |
|---|---|
| allocs | 内存分配情况的采样信息 |
| blocks | 阻塞操作情况的采样信息 |
| cmdline | 显示程序启动命令及参数 |
| goroutine | 显示所有协程的堆栈信息 |
| heap | 堆上内存使用情况的采样信息 |
| profile | CPU 占用情况的采样信息 |
| threadcreate | 系统线程创建情况的采样信息 |
其中allocs 和 heap 采样的信息一致,不过前者是所有对象的内存分配,而 heap 则是活跃对象的内存分配。
我们可以通过 报告生成、Web 可视化界面、交互式终端 三种方式来使用 pprof。这里我使用 wolfogre/go-pprof-practice: go pprof practice. (github.com) 项目结合Web 可视化界面方法介绍pprof工具的基本使用方法。
proflie | CPU
首先,启动项目'main.go'。可以看到以下输出:
2022/05/12 20:01:24 dog.go:38: dog pee
2022/05/12 20:01:24 dog.go:42: dog run
2022/05/12 20:01:24 dog.go:47: dog howl
2022/05/12 20:01:24 wolf.go:27: wolf eat
2022/05/12 20:01:24 wolf.go:31: wolf drink
2022/05/12 20:01:24 wolf.go:40: wolf shit
...
此时项目已经启动成功,pprof 工具的入口会被配置为 http://{host}:6060/debug/pprof, 访问该网址会看到以下信息。
现在可以对系统运行情况进行采样,在终端中执行
go tool pprof -http :8080 http://{host}:6060/debug/pprof/profile?seconds=10
,采样接下来10s的系统运行信息。等待终端输出以下信息后说明采样完成
PS D:\GolandProjects\go-pprof-practice> go tool pprof -http :8080 http://localhost:6060/debug/pprof/profile?seconds=10
Fetching profile over HTTP from http://localhost:6060/debug/pprof/profile?seconds=10
Saved profile in C:\Users\wobuh\pprof\pprof.samples.cpu.004.pb.gz
Serving web UI on http://localhost:8080
此时打开http://{host}:8080/ui可以看到采样结果
通过默认显示的框图可以很直接地发现
tiger 的 Eat 方法占用了大量 CPU 时间,接下来,让我们通过 Source 视图定位消耗大量 CPU 时间的代码。
随后改正该代码即可。
heap | 内存分配
在终端中执行
go tool pprof -http :8080 http://localhost:6060/debug/pprof/heap
对进程的堆信息进行采样,此时不需要提供采样时长信息,因为对内存的采样的时间段是从进程运行开始到执行采样命令的所有时间。 采样完成后,打开 ui 界面,可以看到左上角的 SAMPLE 下拉菜单,其中有四个选项,分别代表分配的对象数、分配的内存数、在使用的对象数、在使用的内存数。
为了使我们的分析更加准确,我们选择分配的内存数,因为这个选项包含了以及被 gc 回收掉的内存。
在这个视图可以清晰地找到消耗大量内存的对象方法。随后,我们定位源码位置。
现在我们可以对代码进行改善
Goroutine
在终端中执行
go tool pprof -http :8080 http://localhost:6060/debug/pprof/goroutine?seconds=10
对goroutine数进行采样。采样结果如下图所示
得到采样结果后,定位问题源代码。
Mutex | 锁竞争
在终端中输入
go tool pprof -http :8080 http://localhost:6060/debug/pprof/mutex?seconds=10
采样 Mutex 锁竞争信息。可以看到采样结果如下。
接下来定位源码位置。