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相关推荐

  1. 白话 Golang pprof

    文章目录 0.前言 1.什么是 pprof 2.pprof 的作用是什么 3.pprof 的使用模式 4.安装 Graphviz 4.应用程序性能分析 4.1 CPU 性能分析 4.2 内存性能分析 ...

  2. golang pprof

    这里填写标题 1. golang pprof 1.1. pprof 实例 2. go tool 2.1. `--inuse/alloc_space` `--inuse/alloc_objects` 区 ...

  3. 使用golang pprof进行性能分析

    golang pprof,说实话自己还一次都没有实际操作过. 最近这几天的需求恰好需要分析下一个看似很简单的服务,内存配置上限是900m,最终在大量并发的时候出现oom的情况. 代码准备 首先代码需要 ...

  4. Golang pprof简介

    目录 概要 pprof的作用 使用方式 交互式常用命令 以profile为例,其余的指标也是用一样的命令 Top N List func Traces web func Base Debug=[num ...

  5. golang pprof工具

    pprof工具 pprof是什么 pprof是分析和显示性能相关数据的工具 pprof读取profile.proto格式的分析抽样集合数据,同时创建报告来展现和帮助分析数据,它能创建包括文本和图型报告 ...

  6. Golang pprof 使用

    目录 什么是 Profile? 两种收集方式 工具型应用 服务型应用 go tool ppof 获取和分析 profile 数据 终端 可视化 什么是 Profile? 在计算机性能调试领域里,pro ...

  7. Golang pprof 性能分析与火焰图

    文章目录 1. 安装graphviz 1.1 下载 graphviz (windows 环境) 1.2 测试graphviz是否安装成功 2. 使用pprof 2.1 修改代码 2.2 火焰图生成 3 ...

  8. 一看就懂系列之Golang的pprof

    前言 这是一篇给网友的文章,正好最近在研究分析golang的性能,我觉得是时候来一个了断了. 正文 1.一句话简介 Golang自带的一款开箱即用的性能监控和分析工具. (全篇看的过程中没必要特意记忆 ...

  9. golang 内存分析/动态追踪

    https://my.oschina.net/ytqvip/blog/1920459 golang pprof 当你的golang程序在运行过程中消耗了超出你理解的内存时,你就需要搞明白,到底是 程序 ...

  10. golang profiling

    这里写目录标题 1. Golang Profiling 1.1. runtime/pprof 包的使用 1.2. net/http/pprof 包的使用 2. 创建火焰图 2.1. 安装 go-tor ...

最新文章

  1. Jupyter Notebook教程
  2. 2030年人类将成为混合式机器人?
  3. OpenCV放大图像:多输出
  4. nosuchelementexception 是什么异常_有甲状腺结节的人为什么越来越多?
  5. python中for和while可以有else_Python 中的for,if-else和while语句
  6. bom实现方块移动_html5实现简单的拼图小游戏
  7. 【python】mysql的操作
  8. C语言为运算表达式添加括号,读书笔记-c语言-运算符与表达式
  9. [AutoSAR]NXP HS12(X) AUTOSAR MCAL编译一下
  10. 增持风行网 百视通在下一盘很大的棋
  11. DragonBones(龙骨动画)在Unity端的使用
  12. 华为荣耀20和x10比较_华为畅享20Pro和荣耀X10哪个好-有什么区别-哪个性价比高
  13. bili弹幕姬_b站弹幕姬|b站弹幕姬下载_v1.0.1.126官方版_9号软件下载
  14. 阿里云Maven仓库地址及设置
  15. 【性能测试】性能测试指标TPS(Transaction per Second)
  16. linux序列拼接软件,EST序列的聚类、拼接以及纠错是怎样进行的,推荐使用那些软件?!...
  17. 哲理故事三百篇(101-150)
  18. 2t移动硬盘linux无法格式化,移动硬盘无法格式化怎么办实际解决方法
  19. gearman 总结
  20. 冯杰的手写艺术签名怎么写好看

热门文章

  1. STM8关于IWDG看门狗和HSI高速时钟和复位的坑
  2. JVM垃圾回收机制GC理解
  3. Python字节串和字节数组
  4. turbotax原理_使用OpenTaxSolver作为TurboTax的开源替代品
  5. 3080猛禽和tuf的区别
  6. 快递邮费计算器 update
  7. 微信小程序 判断是否是全面屏手机和机型
  8. UItableview5--移动单元格位置
  9. 抖音程序员表白代码c语言,程序员过情人节:教你做抖音同款表白程序!
  10. Tron.Legacy.RERip.DVDRip.XViD-TRON 创:战纪/创:光速战记(台)