对之前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