对之前Go 优化的一些补充信息
基本流程
- 在代码中添加采集相关代码
runtime/pprof对于只跑一次的程序进行采集- 如
import "runtime/pprof"; pprof.WriteHeapProfile(f)
- 如
net/http/pprof对于在线服务,提供一个采集端口- 如
import _ "net/http/pprof"; http.ListenAndServe("localhost:8000", nil)开启采集端口
- 如
- 执行命令进行采集
- 如
go tool pprof main http://localhost:8000/debug/pprof/heap - 也可以直接用 curl 进行采集,如
curl "http://localhost:8000/debug/pprof/heap">heap.pprof
- 如
- 命令采集时会自动 dump 到文件,然后开启命令方式与该文件交互
- 如
/home/test/pprof/pprof.test.alloc_objects.alloc_space.inuse_objects.inuse_space.001.pb.gz
- 如
- 能通过命令行交互方式查看已 dump 文件
go tool pprof ./heap.pprof- 如
top、help - 可以直接把交互命令带到参数里,直接查看结果:
go tool pprof -top ./heap.pprof
- 如
- 也可以把文件传到有浏览器的机器,建立一个本地 http SVG 服务器,然后用浏览器访问图形界面
http://localhost:9000/ui/来查看- 用浏览器访问必须先安装图形化组件:
brew install graphviz go tool pprof -http :9000 ./pprof.test.alloc_objects.alloc_space.inuse_objects.inuse_space.001.pb.gz
- 用浏览器访问必须先安装图形化组件:
常用概念
-
heap 分析常用参数
- inuse_space默认参数,分配后未释放的内存- inuse_objects分配后未释放的对象- alloc_space总的分配内存,包含已释放的- alloc_objects总的分配的对象,包含已释放的
-
heap 常见状况
- 存在频繁的 GC 活动,
alloc_space较高而inuse_space较低 - 内存泄漏,
alloc_space和inuse_space都较高 - 初期创建了较大的对象、申请了较大的内存,之后一直被引用未被释放,和内存泄漏类似
- 存在频繁的 GC 活动,
-
执行
top命令时各字段含义:(对 CPU 是占用时间;对 mem 是内存容量;对 object 是对象数量)flat表示该函数自身(不包括其调用的其他函数),在采样总时间内的总消耗flat%当前函数的 flat 占程序总耗时百分比sum%当前加上前面的一行,占程序总耗时百分比cum表示该函数包括其调用的其他函数,在采样总时间内的总消耗cum%该函数加上其所有子函数,占程序总消耗百分比name函数所在包及函数名
-
http SVG 服务的视图
Top和top命令相同Graph以树状展开图形式显示,表示函数/对象的依赖关系- 框越大代表开销越大
- 箭头代表函数调用/对象依赖
FlameGraph火焰图,纵向是调用栈/依赖,横向是开销- 找到最长的栈顶开销,往往就是出问题的地方,也就是 plateaus(平顶)
FlameGraph new颜色风格修改了下,更明显一点Peek在Top基础上增加了下面列:calls、calls%调用下游函数/对象的开销context当前函数作为栈顶向下两层的栈信息,或当前对象作为栈顶,向下两层对象的信息
Source可以看到各个采样点在源码中的位置
采样类型
1 | |
使用技巧
- 运行
go tool pprof时加上--nodefration=0.05可以忽略低于5%的节点 top 20 -cum可指定元素数目和维度,默认 flatgo tool pprof --seconds 25控制采样周期-
go tool pprof --base profile1 profile2把 profile1 作为 base,只显示与 profile2 的差异部分 -
对于需要尽快重启的机器,可以用下面采集脚本先收集后再分析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#!/bin/bash host="localhost" port="8000" # 采集 cpu 信息 curl "http://${host}:${port}/debug/pprof/profile">profile.pprof # 采集 heap 信息 curl "http://${host}:${port}/debug/pprof/heap">heap.pprof # 采集内存分配信息 curl "http://${host}:${port}/debug/pprof/allocs">allocs.pprof # 采集 goroutine 信息 curl "http://${host}:${port}/debug/pprof/goroutine">goroutine.pprof # 采集 mutex 信息 curl "http://${host}:${port}/debug/pprof/mutex">mutex.pprof # 采集 block 信息 curl "http://${host}:${port}/debug/pprof/block">block.pprof