Golang-pprof
Go性能调优
在计算机性能调试领域里,profiling 是指对应用程序的画像,画像就是应用程序使用 CPU 和内存的情况。 Go语言是一个对性能特别看重的语言,因此语言中自带了 profiling 的库,这篇文章就要讲解怎么在 golang 中做 profiling。
Go性能优化
Go语言项目中的性能优化主要有以下几个方面:
- CPU profile:报告程序的 CPU 使用情况,按照一定频率去采集应用程序在 CPU 和寄存器上面的数据
- Memory Profile(Heap Profile):报告程序的内存使用情况
- Block Profiling:报告 goroutines 不在运行状态的情况,可以用来分析和查找死锁等性能瓶颈
- Goroutine Profiling:报告 goroutines 的使用情况,有哪些 goroutine,它们的调用关系是怎样的
采集性能数据#
Go语言内置了获取程序的运行数据的工具,包括以下两个标准库:
runtime/pprof
:采集工具型应用运行数据进行分析net/http/pprof
:采集服务型应用运行时数据进行分析
pprof开启后,每隔一段时间(10ms)就会收集下当前的堆栈信息,获取格格函数占用的CPU以及内存资源;最后通过对这些采样数据进行分析,形成一个性能分析报告。
注意,我们只应该在性能测试的时候才在代码中引入pprof。
工具型应用#
如果你的应用程序是运行一段时间就结束退出类型。那么最好的办法是在应用退出的时候把 profiling 的报告保存到文件中,进行分析。对于这种情况,可以使用runtime/pprof
库。 首先在代码中导入runtime/pprof
工具:
Copy
import "runtime/pprof"
CPU性能分析#
开启CPU性能分析:
Copy
pprof.StartCPUProfile(w io.Writer)
停止CPU性能分析:
Copy
pprof.StopCPUProfile()
应用执行结束后,就会生成一个文件,保存了我们的 CPU profiling 数据。得到采样数据之后,使用go tool pprof
工具进行CPU性能分析。
内存性能优化#
记录程序的堆栈信息
Copy
pprof.WriteHeapProfile(w io.Writer)
得到采样数据之后,使用go tool pprof
工具进行内存性能分析。
go tool pprof
默认是使用-inuse_space
进行统计,还可以使用-inuse-objects
查看分配对象的数量。
服务型应用#
如果你的应用程序是一直运行的,比如 web 应用,那么可以使用net/http/pprof
库,它能够在提供 HTTP 服务进行分析。
如果使用了默认的http.DefaultServeMux
(通常是代码直接使用 http.ListenAndServe(“0.0.0.0:8000”, nil)),只需要在你的web server端代码中按如下方式导入net/http/pprof
Copy
import _ "net/http/pprof"
如果你使用自定义的 Mux,则需要手动注册一些路由规则:
Copy
r.HandleFunc("/debug/pprof/", pprof.Index) r.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline) r.HandleFunc("/debug/pprof/profile", pprof.Profile) r.HandleFunc("/debug/pprof/symbol", pprof.Symbol) r.HandleFunc("/debug/pprof/trace", pprof.Trace)
如果你使用的是gin框架,那么推荐使用"github.com/DeanThompson/ginpprof"
。
不管哪种方式,你的 HTTP 服务都会多出/debug/pprof
endpoint,访问它会得到类似下面的内容:
这个路径下还有几个子页面:
- /debug/pprof/profile:访问这个链接会自动进行 CPU profiling,持续 30s,并生成一个文件供下载
- /debug/pprof/heap: Memory Profiling 的路径,访问这个链接会得到一个内存 Profiling 结果的文件
- /debug/pprof/block:block Profiling 的路径
- /debug/pprof/goroutines:运行的 goroutines 列表,以及调用关系
go tool pprof命令#
不管是工具型应用还是服务型应用,我们使用相应的pprof库获取数据之后,下一步的都要对这些数据进行分析,我们可以使用go tool pprof
命令行工具。
go tool pprof
最简单的使用方式为:
Copy
go tool pprof [binary] [source]
其中:
- binary 是应用的二进制文件,用来解析各种符号;
- source 表示 profile 数据的来源,可以是本地的文件,也可以是 http 地址。
注意事项: 获取的 Profiling 数据是动态的,要想获得有效的数据,请保证应用处于较大的负载(比如正在生成中运行的服务,或者通过其他工具模拟访问压力)。否则如果应用处于空闲状态,得到的结果可能没有任何意义。
具体示例#
首先我们来写一段有问题的代码:
Copy
// runtime_pprof/main.go package main import ( "flag" "fmt" "os" "runtime/pprof" "time" ) // 一段有问题的代码 func logicCode() { var c chan int for { select { case v := <-c: fmt.Printf("recv from chan, value:%v\n", v) default: } } } func main() { var isCPUPprof bool var isMemPprof bool flag.BoolVar(&isCPUPprof, "cpu", false, "turn cpu pprof on") flag.BoolVar(&isMemPprof, "mem", false, "turn mem pprof on") flag.Parse() if isCPUPprof { file, err := os.Create("./cpu.pprof") if err != nil { fmt.Printf("create cpu pprof failed, err:%v\n", err) return } pprof.StartCPUProfile(file) defer pprof.StopCPUProfile() } for i := 0; i < 8; i++ { go logicCode() } time.Sleep(20 * time.Second) if isMemPprof { file, err := os.Create("./mem.pprof") if err != nil { fmt.Printf("create mem pprof failed, err:%v\n", err) return } pprof.WriteHeapProfile(file) file.Close() } }
通过flag我们可以在命令行控制是否开启CPU和Mem的性能分析。 将上面的代码保存并编译成runtime_pprof
可执行文件,执行时加上-cpu
命令行参数如下:
Copy
./runtime_pprof -cpu
等待30秒后会在当前目录下生成一个cpu.pprof
文件。
命令行交互界面#
我们使用go工具链里的pprof
来分析一下。
Copy
go tool pprof cpu.pprof
执行上面的代码会进入交互界面如下:
Copy
runtime_pprof $ go tool pprof cpu.pprof Type: cpu Time: Jun 28, 2019 at 11:28am (CST) Duration: 20.13s, Total samples = 1.91mins (568.60%) Entering interactive mode (type "help" for commands, "o" for options) (pprof)
我们可以在交互界面输入top3
来查看程序中占用CPU前3位的函数:
Copy
(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的总耗时百分比
- 最后一列:函数名称
在大多数的情况下,我们可以通过分析这五列得出一个应用程序的运行情况,并对程序进行优化。
我们还可以使用list 函数名
命令查看具体的函数分析,例如执行list logicCode
查看我们编写的函数的详细分析。
Copy
(pprof) list logicCode Total: 1.91mins ROUTINE ================ main.logicCode in .../runtime_pprof/main.go 22.64s 1.91mins (flat, cum) 99.91% of Total . . 12:func logicCode() { . . 13: var c chan int . . 14: for { . . 15: select { . . 16: case v := <-c: 22.64s 1.91mins 17: fmt.Printf("recv from chan, value:%v\n", v) . . 18: default: . . 19: . . 20: } . . 21: } . . 22:}
通过分析发现大部分CPU资源被17行占用,我们分析出select语句中的default没有内容会导致上面的case v:=<-c:
一直执行。我们在default分支添加一行time.Sleep(time.Second)
即可。
图形化#
或者可以直接输入web,通过svg图的方式查看程序中详细的CPU占用情况。 想要查看图形化的界面首先需要安装graphviz图形化工具。
Mac:
Copy
brew install graphviz
Windows: 下载graphviz 将graphviz
安装目录下的bin文件夹添加到Path环境变量中。 在终端输入dot -version
查看是否安装成功。
关于图形
的说明: 每个框代表一个函数,理论上框的越大表示占用的CPU资源越多。 方框之间的线条代表函数之间的调用关系。 线条上的数字表示函数调用的次数。 方框中的第一行数字表示当前函数占用CPU的百分比,第二行数字表示当前函数累计占用CPU的百分比。
go-torch和火焰图#
火焰图(Flame Graph)是 Bredan Gregg 创建的一种性能分析图表,因为它的样子近似
Golang-pprof相关推荐
- 白话 Golang pprof
文章目录 0.前言 1.什么是 pprof 2.pprof 的作用是什么 3.pprof 的使用模式 4.安装 Graphviz 4.应用程序性能分析 4.1 CPU 性能分析 4.2 内存性能分析 ...
- golang pprof
这里填写标题 1. golang pprof 1.1. pprof 实例 2. go tool 2.1. `--inuse/alloc_space` `--inuse/alloc_objects` 区 ...
- 使用golang pprof进行性能分析
golang pprof,说实话自己还一次都没有实际操作过. 最近这几天的需求恰好需要分析下一个看似很简单的服务,内存配置上限是900m,最终在大量并发的时候出现oom的情况. 代码准备 首先代码需要 ...
- Golang pprof简介
目录 概要 pprof的作用 使用方式 交互式常用命令 以profile为例,其余的指标也是用一样的命令 Top N List func Traces web func Base Debug=[num ...
- golang pprof工具
pprof工具 pprof是什么 pprof是分析和显示性能相关数据的工具 pprof读取profile.proto格式的分析抽样集合数据,同时创建报告来展现和帮助分析数据,它能创建包括文本和图型报告 ...
- Golang pprof 使用
目录 什么是 Profile? 两种收集方式 工具型应用 服务型应用 go tool ppof 获取和分析 profile 数据 终端 可视化 什么是 Profile? 在计算机性能调试领域里,pro ...
- Golang pprof 性能分析与火焰图
文章目录 1. 安装graphviz 1.1 下载 graphviz (windows 环境) 1.2 测试graphviz是否安装成功 2. 使用pprof 2.1 修改代码 2.2 火焰图生成 3 ...
- 一看就懂系列之Golang的pprof
前言 这是一篇给网友的文章,正好最近在研究分析golang的性能,我觉得是时候来一个了断了. 正文 1.一句话简介 Golang自带的一款开箱即用的性能监控和分析工具. (全篇看的过程中没必要特意记忆 ...
- golang 内存分析/动态追踪
https://my.oschina.net/ytqvip/blog/1920459 golang pprof 当你的golang程序在运行过程中消耗了超出你理解的内存时,你就需要搞明白,到底是 程序 ...
- golang profiling
这里写目录标题 1. Golang Profiling 1.1. runtime/pprof 包的使用 1.2. net/http/pprof 包的使用 2. 创建火焰图 2.1. 安装 go-tor ...
最新文章
- Jupyter Notebook教程
- 2030年人类将成为混合式机器人?
- OpenCV放大图像:多输出
- nosuchelementexception 是什么异常_有甲状腺结节的人为什么越来越多?
- python中for和while可以有else_Python 中的for,if-else和while语句
- bom实现方块移动_html5实现简单的拼图小游戏
- 【python】mysql的操作
- C语言为运算表达式添加括号,读书笔记-c语言-运算符与表达式
- [AutoSAR]NXP HS12(X) AUTOSAR MCAL编译一下
- 增持风行网 百视通在下一盘很大的棋
- DragonBones(龙骨动画)在Unity端的使用
- 华为荣耀20和x10比较_华为畅享20Pro和荣耀X10哪个好-有什么区别-哪个性价比高
- bili弹幕姬_b站弹幕姬|b站弹幕姬下载_v1.0.1.126官方版_9号软件下载
- 阿里云Maven仓库地址及设置
- 【性能测试】性能测试指标TPS(Transaction per Second)
- linux序列拼接软件,EST序列的聚类、拼接以及纠错是怎样进行的,推荐使用那些软件?!...
- 哲理故事三百篇(101-150)
- 2t移动硬盘linux无法格式化,移动硬盘无法格式化怎么办实际解决方法
- gearman 总结
- 冯杰的手写艺术签名怎么写好看
热门文章
- STM8关于IWDG看门狗和HSI高速时钟和复位的坑
- JVM垃圾回收机制GC理解
- Python字节串和字节数组
- turbotax原理_使用OpenTaxSolver作为TurboTax的开源替代品
- 3080猛禽和tuf的区别
- 快递邮费计算器 update
- 微信小程序 判断是否是全面屏手机和机型
- UItableview5--移动单元格位置
- 抖音程序员表白代码c语言,程序员过情人节:教你做抖音同款表白程序!
- Tron.Legacy.RERip.DVDRip.XViD-TRON 创:战纪/创:光速战记(台)