[TOC]
go中提供了pprof包来做代码的性能监控,在两个地方有包:
* net/http/pprof
* runtime/pprof
其实net/http/pprof中只是使用runtime/pprof包来进行封装了一下,并在http端口上暴露出来
~~~
#web服务器:
import (
"net/http"
_ "net/http/pprof"
)
#一般应用程序(实际应用无web交互)
import (
"net/http"
_ "runtime/pprof"
)
~~~
# 使用 net/http/pprof 做WEB服务器的性能监控
如果你的go程序是用http包启动的web服务器,想要查看自己的web服务器的状态。这个时候就可以选择net/http/pprof。
~~~
import _ "net/http/pprof"
~~~
然后就可以在浏览器中使用http://localhost:port/debug/pprof/ 直接看到当前web服务的状态,包括CPU占用情况和内存使用情况等。
当然,非WEB的也可以用下面方式启动WEB。
在 main 方法中增加
~~~
func main() {
go func() {
http.ListenAndServe("localhost:6060", nil)
}()
~~~
![](https://box.kancloud.cn/71f311da85b2a3abcf80eb071174d337_356x266.png)
# CPU消耗分析
**使用 runtime/pprof 做应用程序性能监控**
关键代码:
~~~
import "runtime/pprof"
func main() {
f, err := os.OpenFile("./tmp/cpu.prof", os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
log.Fatal(err)
}
defer f.Close()
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
~~~
注意,有时候 defer f.Close(), defer pprof.StopCPUProfile() 会执行不到,这时候我们就会看到 prof 文件是空的, 我们需要在自己代码退出的地方,增加上下面两行,确保写文件内容了。
~~~
pprof.StopCPUProfile()
f.Close()
~~~
# 对产生的文件进行分析:
我们可以使用 go tool pprof (应用程序) (应用程序的prof文件) 方式来对这个 prof 文件进行分析。
~~~
$ go tool pprof HuaRongDao ./tmp/cpu.prof
Entering interactive mode (type "help" for commands)
(pprof)
~~~
一些常用 pprof 的命令:
# top
在默认情况下,top命令会输出以本地取样计数为顺序的列表。我们可以把这个列表叫做本地取样计数排名列表。
~~~
(pprof) top
2700ms of 3200ms total (84.38%)
Dropped 58 nodes (cum <= 16ms)
Showing top 10 nodes out of 111 (cum >= 80ms)
flat flat% sum% cum cum%
670ms 20.94% 20.94% 670ms 20.94% runtime.mach\_semaphore\_signal
580ms 18.12% 39.06% 590ms 18.44% runtime.cgocall
370ms 11.56% 50.62% 370ms 11.56% runtime.mach\_semaphore\_wait
360ms 11.25% 61.88% 360ms 11.25% runtime.memmove
210ms 6.56% 68.44% 580ms 18.12% golang.org/x/mobile/gl.(\*context).DoWork
120ms 3.75% 72.19% 120ms 3.75% runtime.usleep
110ms 3.44% 75.62% 110ms 3.44% image/png.filterPaeth
100ms 3.12% 78.75% 160ms 5.00% compress/flate.(\*decompressor).huffSym
100ms 3.12% 81.88% 100ms 3.12% image/draw.drawNRGBASrc
80ms 2.50% 84.38% 80ms 2.50% runtime.memclr
(pprof)
~~~
参考:[https://github.com/hyper-carrot/go\_command\_tutorial/blob/master/0.12.md](https://github.com/hyper-carrot/go_command_tutorial/blob/master/0.12.md "https://github.com/hyper-carrot/go_command_tutorial/blob/master/0.12.md")
默认情况下top命令会列出前10项内容。但是如果在top命令后面紧跟一个数字,那么其列出的项数就会与这个数字相同
# web
与gv命令类似,web命令也会用图形化的方式来显示概要文件。但不同的是,web命令是在一个Web浏览器中显示它。如果你的Web浏览器已经启动,那么它的显示速度会非常快。如果想改变所使用的Web浏览器,可以在Linux下设置符号链接/etc/alternatives/gnome-www-browser或/etc/alternatives/x-www-browser,或在OS X下改变SVG文件的关联Finder。
mac 下 修改默认打开方式: 右键一个想处理的文件,按alt 键(lion)出现always open with,然后打开,整个过程中, 先右键,然后一直按 alt, 一直到打开为止
![](https://box.kancloud.cn/177413990fa2d80b70794c904d6b27e8_759x426.png)
参考资料:
go tool pprof
[https://github.com/hyper-carrot/go\_command\_tutorial/blob/master/0.12.md](https://github.com/hyper-carrot/go_command_tutorial/blob/master/0.12.md "https://github.com/hyper-carrot/go_command_tutorial/blob/master/0.12.md")
Go的pprof使用
[http://www.cnblogs.com/yjf512/archive/2012/12/27/2835331.html](http://www.cnblogs.com/yjf512/archive/2012/12/27/2835331.html "http://www.cnblogs.com/yjf512/archive/2012/12/27/2835331.html")
Profiling Go Programs
[https://blog.golang.org/profiling-go-programs](https://blog.golang.org/profiling-go-programs "https://blog.golang.org/profiling-go-programs")
# 内存泄漏或消耗分析
关键代码
~~~
fm, err := os.OpenFile("./tmp/mem.out", os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
log.Fatal(err)
}
pprof.WriteHeapProfile(fm)
fm.Close()
~~~
在我们需要生成当时的内存情况时,只需要执行上面代码即可。
触发的条件可以通过 http 的一个接口,或者退出时,或者接收到某个特殊信号,这些逻辑就需要自己实现了。
分析方法,跟之上CPU的分析方法一致
![](https://box.kancloud.cn/9d485d5531680fcdfbfe4f64733f4b84_608x350.png)
\[golang\]内存不断增长bytes.makeSlice
[http://studygolang.com/articles/2763](http://studygolang.com/articles/2763 "http://studygolang.com/articles/2763")
# graphviz可视化
下面是一个使用pprof长时间运行的例子:
![](https://box.kancloud.cn/99c7e1874b7bae84627548fa7bab9581_655x307.png)
pprof能够借助grapgviz产生程序的调用图。默认情况下pprof基于对程序的30秒采样产生调用图。
* 图中的连线代表对方法的调用, 连线上的标签代表指定的方法调用的采样值(译者注:go tool pprof显示的是调用时间)。
* 方框的大小与方法运行的采样值的大小有关。
* 每个方框由两个标签:一个是方法运行的时间占比,一个是它在采样的堆栈中出现的时间占比(译者注: 前者你可以看成flat时间,后者看成cumulate时间)
**在Mac上安装工具**:
~~~
brew install gperftools$ brew install graphviz
~~~
~~~
pprof --web localhost:6060/debug
~~~
我并没有使用上面的工具,因为Go开发环境已经集成了pprof工具,所以你不需要安装gperftools工具,而且使用的命令和上面的命令不一样。
当然graphviz是必装的。
你可以通过下面的命令采集30s的数据并生成SVG调用图:
~~~
go tool pprof -web http://127.0.0.1:6060/debug/pprof/profile
~~~
Heap profile:
~~~
go tool pprof --text http://localhost:8080/debug/pprof/heap
~~~
CPU profile:
~~~
go tool pprof --text http://localhost:8080/debug/pprof/profile
~~~
Goroutine blocking profile:
~~~
go tool pprof --text http://localhost:8080/debug/pprof/block
~~~
# go-torch
和pprof一样,它也采用30秒的采样数据生成火焰图。
* 栈帧(Stack frame,调用链)垂直堆叠,显示栈的深度
* 帧的宽度代表一个方法的运行的时间占比
* 如果一个方法被调用者调用,它会显示多次,分列在不同的调用者的堆栈上。(译者注:这点和pprof工具不同,pprof至显示一个方法的框,上面的时间标签是所有的调用者调用的时间)
* 颜色是任意的(arbitrary), 横坐标根据字母顺序排列
需要安装go-torch工具和brandangregg的火焰图生成脚本:
~~~
go get github.com/uber/go-torch
git clone git@github.com:brendangregg/FlameGraph.git
export PATH-$PATH:/path/to/FlameGraph
go-torch --file "torch.svg" --url http://localhost:6060
~~~
- 基础
- 简介
- 主要特征
- 变量和常量
- 编码转换
- 数组
- byte与rune
- big
- sort接口
- 和mysql类型对应
- 函数
- 闭包
- 工作区
- 复合类型
- 指针
- 切片
- map
- 结构体
- sync.Map
- 随机数
- 面向对象
- 匿名组合
- 方法
- 接口
- 权限
- 类型查询
- 异常处理
- error
- panic
- recover
- 自定义错误
- 字符串处理
- 正则表达式
- json
- 文件操作
- os
- 文件读写
- 目录
- bufio
- ioutil
- gob
- 栈帧的内存布局
- shell
- 时间处理
- time详情
- time使用
- new和make的区别
- container
- list
- heap
- ring
- 测试
- 单元测试
- Mock依赖
- delve
- 命令
- TestMain
- path和filepath包
- log日志
- 反射
- 详解
- plugin包
- 信号
- goto
- 协程
- 简介
- 创建
- 协程退出
- runtime
- channel
- select
- 死锁
- 互斥锁
- 读写锁
- 条件变量
- 嵌套
- 计算单个协程占用内存
- 执行规则
- 原子操作
- WaitGroup
- 定时器
- 对象池
- sync.once
- 网络编程
- 分层模型
- socket
- tcp
- udp
- 服务端
- 客户端
- 并发服务器
- Http
- 简介
- http服务器
- http客户端
- 爬虫
- 平滑重启
- context
- httptest
- 优雅中止
- web服务平滑重启
- beego
- 安装
- 路由器
- orm
- 单表增删改查
- 多级表
- orm使用
- 高级查询
- 关系查询
- SQL查询
- 元数据二次定义
- 控制器
- 参数解析
- 过滤器
- 数据输出
- 表单数据验证
- 错误处理
- 日志
- 模块
- cache
- task
- 调试模块
- config
- 部署
- 一些包
- gjson
- goredis
- collection
- sjson
- redigo
- aliyunoss
- 密码
- 对称加密
- 非对称加密
- 单向散列函数
- 消息认证
- 数字签名
- mysql优化
- 常见错误
- go run的错误
- 新手常见错误
- 中级错误
- 高级错误
- 常用工具
- 协程-泄露
- go env
- gometalinter代码检查
- go build
- go clean
- go test
- 包管理器
- go mod
- gopm
- go fmt
- pprof
- 提高编译
- go get
- 代理
- 其他的知识
- go内存对齐
- 细节总结
- nginx路由匹配
- 一些博客
- redis为什么快
- cpu高速缓存
- 常用命令
- Go 永久阻塞的方法
- 常用技巧
- 密码加密解密
- for 循环迭代变量
- 备注
- 垃圾回收
- 协程和纤程
- tar-gz
- 红包算法
- 解决golang.org/x 下载失败
- 逃逸分析
- docker
- 镜像
- 容器
- 数据卷
- 网络管理
- 网络模式
- dockerfile
- docker-composer
- 微服务
- protoBuf
- GRPC
- tls
- consul
- micro
- crontab
- shell调用
- gorhill/cronexpr
- raft
- go操作etcd
- mongodb