Go性能分析工具使用(内存排查)
性能分析工具帮助定位内存问题和优化方向。
pprof内存分析
启用pprof
Go
import (
"net/http"
"net/http/pprof"
)
func main() {
// 注册pprof路由
go func() {
http.ListenAndServe(":6060", nil)
}()
// 你的程序...
}
采集内存profile
Bash
# 内存分配profile
go tool pprof http://localhost:6060/debug/pprof/allocs
# heap使用profile
go tool pprof http://localhost:6060/debug/pprof/heap
# 保存profile文件
curl -o heap.prof http://localhost:6060/debug/pprof/heap
go tool pprof heap.prof
分析内存分配
Bash
# 进入交互模式
go tool pprof http://localhost:6060/debug/pprof/allocs
# 查看分配top
(pprof) top10
flat flat% sum% cum cum%
10.5MB 42.1% 42.1% 10.5MB 42.1% main.processData
5.2MB 20.8% 62.9% 5.2MB 20.8% main.newBuffer
...
# 查看调用链
(pprof) list processData
// 显示源码和分配量
# 查看调用图
(pprof) web
heap dump分析
heap指标
Bash
# 查看heap统计
(pprof) stats
Total: 50MB
HeapAlloc: 30MB
HeapSys: 40MB
...
# 查看对象类型分布
(pprof) sample_index=alloc_space
(pprof) top
采样类型
Go
// allocs profile采样类型
alloc_space // 累计分配空间
alloc_objects // 累计分配对象数
// heap profile采样类型
inuse_space // 正在使用空间
inuse_objects // 正在使用对象数
Bash
# 切换采样类型
(pprof) sample_index=inuse_space
(pprof) top
runtime.MemStats监控
Go
import "runtime"
func monitorMemory() {
var m runtime.MemStats
runtime.ReadMemStats(&m)
fmt.Printf("堆分配: %d MB\n", m.HeapAlloc/1024/1024)
fmt.Printf("堆系统: %d MB\n", m.HeapSys/1024/1024)
fmt.Printf("GC次数: %d\n", m.NumGC)
fmt.Printf("GC暂停: %d ms\n", m.PauseTotalNs/1e6)
fmt.Printf("分配次数: %d\n", m.Mallocs)
fmt.Printf("释放次数: %d\n", m.Frees)
}
GC压力分析
查看GC日志
Bash
# 启用GC日志
GODEBUG=gctrace=1 go run main.go
# 输出示例
gc 1 @0.001s 0%: 0.015+0.5+0.023 ms clock, 0.12+0.5/0.5/0+0.18 ms cpu, 4->4->0 MB, 4 MB goal, 4 P
解读:
Go
gc 1 # 第1次GC
@0.001s # 程序启动后0.001秒
0% # GC占用CPU 0%
0.015+0.5+0.023 ms # STW各阶段时间
4->4->0 MB # 堆大小变化
4 MB goal # GC目标阈值
4 P # P数量
强制GC测试
Go
func testGCPressure() {
var m runtime.MemStats
for i := 0; i < 10; i++ {
// 执行操作
processData()
// 强制GC
runtime.GC()
// 检查内存
runtime.ReadMemStats(&m)
fmt.Printf("堆大小: %d MB\n", m.HeapAlloc/1024/1024)
}
}
trace分析
采集trace
Bash
import "runtime/trace"
func main() {
trace.Start(os.Stderr)
defer trace.Stop()
// 你的程序...
}
Bash
# 或通过pprof采集
curl -o trace.out http://localhost:6060/debug/pprof/trace
# 分析trace
go tool trace trace.out
trace界面查看
- Goroutine创建和调度
- GC事件和时间
- 网络阻塞
- 系统调用阻塞
常见内存问题排查
1. 内存泄漏
Bash
# 对比多次heap dump
curl -o heap1.prof http://localhost:6060/debug/pprof/heap
# 运行一段时间
curl -o heap2.prof http://localhost:6060/debug/pprof/heap
# 对比差异
go tool pprof -base heap1.prof heap2.prof
(pprof) top
# 查看增长的对象
2. 分配热点
Bash
# 查看分配最多的函数
go tool pprof -sample_index=alloc_space http://localhost:6060/debug/pprof/allocs
(pprof) top
(pprof) list <函数名>
3. GC频繁
text
# 查看GC频率
GODEBUG=gctrace=1 go run main.go
# 如果GC间隔很短(<10ms),考虑:
# 1. 减少分配
# 2. 增加GOGC
GOGC=200 go run main.go
内存排查命令汇总
| 命令 | 用途 |
|---|---|
pprof allocs | 分析分配热点 |
pprof heap | 分析heap使用 |
MemStats | 实时监控指标 |
gctrace=1 | GC日志分析 |
trace | 调度和GC可视化 |
-race | 数据竞争检测 |
要点总结
- pprof分析内存分配和使用
- allocs看分配热点,heap看当前使用
- MemStats监控实时内存指标
- GODEBUG=gctrace=1查看GC频率
- trace可视化GC和调度
- 对比heap dump定位内存泄漏
- 优化前先用工具定位问题
📝 发现内容有误?点击此处直接编辑