Go 性能调优
https://www.liwenzhou.com/posts/Go/pprof/
四个方面
- CPU profile:报告程序的 CPU 使用情况,按照一定频率去采集应用程序在 CPU 和寄存器上面的数据
- Memory profile(Heap Profile:内存使用情况
- Block profiling:goroutine 不在运行的状态,可以用来分析和查找死锁等性能瓶颈
- Goroutine profiling:goroutines的使用情况,以及调用关系
Go语言内置了获取程序的运行数据的工具,包括以下两个标准库:
runtime/pprof:采集工具型应用运行数据进行分析net/http/pprof:采集服务型应用运行时数据进行分析
CPU的采集
pprof.StartCPUProfile(w io.Writer)
pprof.StopCPUProfile()
得到采样数据之后,使用go tool pprof工具进行内存性能分析。
内存
pprof.WriteHeapProfile(w io.Writer)
go tool pprof默认是使用-inuse_space进行统计,还可以使用-inuse-objects查看分配对象的数量。
import _ “net/http/pprof”
你的 HTTP 服务都会多出/debug/pprof endpoint
![[Pasted image 20250802111822.png]]
(pprof) top3
Showing nodes accounting for 100.37s, 87.68% of 114.47s total
Dropped 17 nodes (cum <= 0.57s)
Showing top 3 nodes out of 4
flat flat% sum% cum cum%
42.52s 37.15% 37.15% 91.73s 80.13% runtime.selectnbrecv
35.21s 30.76% 67.90% 39.49s 34.50% runtime.chanrecv
22.64s 19.78% 87.68% 114.37s 99.91% main.logicCode
其中:
- flat:当前函数占用CPU的耗时
- flat%::当前函数占用CPU的耗时百分比
- sun%:函数占用CPU的耗时累计百分比
- cum:当前函数加上调用当前函数的函数占用CPU的总耗时
- cum%:当前函数加上调用当前函数的函数占用CPU的总耗时百分比
- 最后一列:函数名称
在大多数的情况下,我们可以通过分析这五列得出一个应用程序的运行情况,并对程序进行优化。
可视化显示
需要安装 graphviz
go tool pprof -http :8090 ./profile
Serving web UI on [<http://localhost:8090>](<http://localhost:8090/>)
→
火焰图 go-torch(依赖FlameGraph)
go install github.com/uber/go-torch
go-torch
Usage:
go-torch [options] [binary] <profile source>
pprof Options:
-u, --url= Base URL of your Go program (default: <http://localhost:8080>)
--suffix= URL path of pprof profile (default: /debug/pprof/profile)
-b, --binaryinput= File path of previously saved binary profile. (binary profile is anything accepted by
<https://golang.org/cmd/pprof>)
--binaryname= File path of the binary that the binaryinput is for, used for pprof inputs
-t, --seconds= Number of seconds to profile for (default: 30)
--pprofArgs= Extra arguments for pprof
Output Options:
-f, --file= Output file name (must be .svg) (default: torch.svg)
-p, --print Print the generated svg to stdout instead of writing to file
-r, --raw Print the raw call graph output to stdout instead of creating a flame graph; use with Brendan Gregg's
flame graph perl script (see <https://github.com/brendangregg/FlameGraph>)
--title= Graph title to display in the output file (default: Flame Graph)
--width= Generated graph width (default: 1200)
--hash Colors are keyed by function name hash
--colors= set color palette. choices are: hot (default), mem, io, wakeup, chain, java, js, perl, red, green,
blue, aqua, yellow, purple, orange
--cp Use consistent palette (palette.map)
--reverse Generate stack-reversed flame graph
--inverted icicle graph
Help Options:
-h, --help Show this help message
-
Wrap 安装 flamegraph
~/Downloads 1 block Install flamegraph scripts and add them to your PATH.
� I’ll install the flamegraph scripts from Brendan Gregg’s FlameGraph repository and add them to your PATH. This will allow go-torch to generate flame graphs properly. Let me install it in your home directory instead, which doesn’t require sudo permissions: Great! Now let me check what scripts are available and add the FlameGraph directory to your PATH: Perfect! The FlameGraph scripts are now installed. I need to make sure the key script (flamegraph.pl) is executable and add the directory to your PATH. Let me add the FlameGraph directory to your PATH by updating your .zshrc file: /Users/elonnzhang/.zshrc Manage AI Autonomy permissions Now I’ll add the FlameGraph directory to your PATH in the .zshrc file: Now let me reload the shell configuration and test that the flamegraph scripts are accessible: Excellent! Let me test that the flamegraph.pl script works: Perfect! Everything is now set up correctly. Let me verify that go-torch can now find the flamegraph scripts: The error is expected since I provided invalid input, but it confirms the script is working. Let me clean up the test file: Installation Complete! ✅
Here’s what I’ve accomplished:
- Downloaded FlameGraph scripts from Brendan Gregg’s repository to /Users/elonnzhang/FlameGraph
- Added FlameGraph directory to PATH in your .zshrc file
- Added Go bin directory to PATH so go-torch is accessible
- Verified both tools are working and accessible from anywhere
What’s now available: • go-torch - The Go flame graph generator • flamegraph.pl - The main flame graph script • All other FlameGraph utilities (stackcollapse scripts, etc.)
Your updated PATH includes: • /opt/homebrew/opt/mysql@8.4/bin (existing) • $(go env GOPATH)/bin (for go-torch) • /Users/elonnzhang/FlameGraph (for flamegraph scripts)
Now you can run your original go-torch command without the “Cannot find flamegraph scripts” error! The command should work properly: bash
压测工具
https://github.com/adjust/go-wrk
./go-wrk -c 1000 -t=8 -n=10000 \\
-m="POST" \\
-H='x-tdn-timestamp: 1752372771' \\
-H='x-tdn-nonce: hvo4ul49uk' \\
-H='x-tdn-appid: mdb_test' \\
-H='x-tdn-signature: D4F4642355B6E77AD21D8AC156C7701864AB505F504D305A9F602B983E50432E' \\
-H='staffname: elonnzhang' \\
-H='Content-Type: application/json' \\
-b '{
"connect_type": 1,
"instance_type": "tdsql",
"connect_info": {
"host": "9.134.194.8",
"port": 3306,
"user": "root",
"password": "6ea47ab45f506a2eed7b0b5be76eb9c262be2c5ca0143ac869c21f",
"charset": "utf8",
"timeout": 1000,
"params":{}
},
"db_name": "test_db",
"sql": "select * from big_table",
"limit": "10000",
"timeout": 0,
"async": false,
"batch": false,
"interval": 0
}' <http://9.135.33.6:8008/api/db/execSQL>
https://github.com/tsliwowicz/go-wrk
go-wrk \\
-H 'x-tdn-timestamp: 1752372771' \\
-H 'x-tdn-nonce: hvo4ul49uk' \\
-H 'x-tdn-appid: mdb_test' \\
-H 'x-tdn-signature: D4F4642355B6E77AD21D8AC156C7701864AB505F504D305A9F602B983E50432E' \\
-H 'staffname: elonnzhang' \\
-H 'Content-Type: application/json' \\
-M POST \\
-body '{
"connect_type": 1,
"instance_type": "tdsql",
"connect_info": {
"host": "9.134.194.8",
"port": 3306,
"user": "root",
"password": "6ea47ab45f506a2eed7b0b5be76eb9c262be2c5ca0143ac869c21f",
"charset": "utf8",
"timeout": 1000,
"params":{}
},
"db_name": "test_db",
"sql": "select * from big_table",
"limit": "1000",
"timeout": 0,
"async": false,
"batch": false,
"interval": 0
}' -d 35 '<http://9.135.33.6:8008/api/db/execSQL>'