Go性能分析工具pprof详解_go pprof-程序员宅基地

技术标签: golang  go  后端  开发语言  


一、什么是pprof

pprof是Go官方提供的性能分析工具,可以分析程序的运行情况,并且提供可视化的功能。prof是profile(画像)的缩写,使用pprof可以分析以下几种指标数据:
在这里插入图片描述

  • allocs:程序启动之后内存分配的情况
  • block:导致阻塞操作的一些堆栈跟踪信息
  • cmdline:当前程序启动的命令行
  • goroutine:所有当前 goroutine 的堆栈跟踪信息
  • heap:程序在当前堆上内存分配的情况
  • mutex:锁资源的竞争的堆栈信息
  • profileCPU profile文件。可以在 debug/pprof?seconds=x秒 GET 参数中指定持续时间。获取pprof文件后,使用 go tool pprof x.prof命令分析pprof文件。
  • threadcreate:系统线程的使用情况
  • trace:当前系统的代码执行的链路情况

使用pprof工具主要分析以下几种指标:

  • CPU ProfilingCPU 分析,按照一定的频率采集所监听的应用程序 CPU(含寄存器)的使用情况,可确定应用程序在主动消耗 CPU 周期时花费时间的位置

  • Memory Profiling:内存分析,在应用程序进行堆分配时记录堆栈跟踪,用于监视当前和历史内存使用情况,以及检查内存泄漏

  • Block Profiling:阻塞分析,记录 goroutine 阻塞等待同步(包括定时器通道)的位置

  • Mutex Profiling:互斥锁分析,报告互斥锁的竞争情况。

当程序存在内存或者CPU飙升的情况时,我们可以通过pprof工具来查询问题出现的根源。


二、怎么使用pprof

pprof包含两个相关的库:

  1. runtime/pprof
    主要应用于工具型应用。包含脚本、定时任务等。
    如:对于只跑一次的程序,例如每天只跑一次的离线预处理程序,调用 pprof 包提供的函数,手动开启性能数据采集
  2. net/http/pprof
    主要应用于服务型应用。包含HTTP服务,GRPC服务等。
    如:对于在线服务,对于一个 HTTP Server,访问 pprof 提供的 HTTP 接口,获得性能数据。当然,实际上这里底层也是调用的 runtime/pprof提供的函数,封装成接口对外提供网络访问。

1. 工具型应用

工具型应用主要使用runtime/pprof包实现性能分析。

func main() {
    
	// --- cpu 分析示例 start---
	// 创建cpu分析文件
	fc, err := os.Create("./cpu.prof")
	if err != nil {
    
		fmt.Println("create cpu.prof err:", err.Error())
		return
	}
	defer fc.Close()

	// 开始分析cpu
	err = pprof.StartCPUProfile(fc)
	if err == nil {
    
		defer pprof.StopCPUProfile()
	}
	// --- cpu 分析示例 end---
	
	var count int
	for i := 0; i < 10000; i++ {
    
		count++
	}

	// --- 内存 分析示例 start---
	fm, err := os.Create("./memory.prof")
	if err != nil {
    
		fmt.Println("create memory.prof err:", err.Error())
		return
	}
	defer fm.Close()

	// 开始分析内存
	err = pprof.WriteHeapProfile(fm)
	if err != nil {
    
		fmt.Println("write heap prof err:", err.Error())
		return
	}
	// --- 内存 分析示例 end---

	for i := 0; i < 10000; i++ {
    
		count++
	}
	fmt.Println("do finish......count:", count)
}

执行go run main.go后,在代码目录下,可以看到生成了cpu.profmemory.prof文件。
通过执行go tool pprof ./memory.prof或者
go tool pprof -http=:8888 ./memory.prof进入命令行模式或者web页面进行性能分析。

执行go tool pprof ./memory.prof进入命令行:
cmd memory.prof

执行go tool -http=:8888 pprof ./memory.prof可进入web页面,更方便查看:
http memory.prof
页面展示效果:
web memory.prof
SAMPLE各个标签的含义解释:
在这里插入图片描述

2. 服务型应用

对于服务类型的应用,主要在服务内部匿名引入net/http/pprof包,然后通过HTTP访问pprof页面。
匿名引入方式为:import _ "net/http/pprof"

package main

import (
	"fmt"
	"net/http"
	_ "net/http/pprof"
)

func main() {
    
	http.HandleFunc("/", hello)
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
    
		fmt.Println("ListenAndServe Err:", err.Error())
		return
	}
}

func hello(resp http.ResponseWriter, req *http.Request) {
    
	fmt.Fprintln(resp, "Hello World, Are You OK?")
}

执行http://localhost:8080/debug/pprof/可以看到画像信息:
在这里插入图片描述

但是需要注意,如果HTTP服务不是通过
http.ListenAndServe(":8080", nil)启动的,而是指定第二个参数启动的话,需要自己注册pprof路由。

net/http/pprof/pprof.go的官方源码注释中也提到此种情况:

If you are not using DefaultServeMux, you will have to register handlers with the mux you are using.
如果您不使用DefaultServeMux,则必须向所使用的多路复用器注册pprof处理程序
http.ListenAndServe函数可以传递handler,如果handler不为nil,则说明研发自定义了 ServeMux,否则用的是默认DefaultServeMux

net/http/pprof包中,有init函数

func init() {
    
   http.HandleFunc("/debug/pprof/", Index)
   http.HandleFunc("/debug/pprof/cmdline", Cmdline)
   http.HandleFunc("/debug/pprof/profile", Profile)
   http.HandleFunc("/debug/pprof/symbol", Symbol)
   http.HandleFunc("/debug/pprof/trace", Trace)
}

所以如果使用默认ServeMux,则不需要注册,但是如果使用自定义的ServeMux,则需要增加注册后,才能获取到pprof

// 自己注册这几个函数
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)

另外一种启动pprof的方式在生产环境中更加常用:通过协程另起一个HTTP服务,单独用作pprof分析:

func RegisterProf() {
    
	go func() {
    
		if err := http.ListenAndServe(":6060", nil); err != nil {
    
			panic("pprof server start error: " + err.Error())
		}
	}()
}

三、pprof数据分析

GO官方提供了go tool pprof工具来帮助我们分析pprof生成的数据文件。
使用go tool pprof分析数据,主要有两种模式:

  1. 命令行交互模式
    go tool pprof [file_pprof|url_pprof]
  2. web页面模式
    go tool pprof -http=:6666 [file_pprof|url_pprof]
    其中,file_pprof表示生成的prof分析文件,如cpu.profurl_pprof表示远端服务开启的pprof访问,如http://localhost:8080/debug/pprof/profile

进入命令行交互模式后,可以使用help查看所有子命令,使用help <cmd|option>查看子命令使用方法。如 help、help top

CPU Profiling

浏览器访问/debug/pprof/profile会自动进行 CPU profiling,默认持续 30s,并生成一个文件供下载,可以通过带参数?seconds=60进行60秒的数据采集。

为了模拟请求,使用ab进行压测,
ab -k -c 1 -t 180 -n 100000000 http://localhost:8080/hello

执行go tool pprof http://localhost:8080/debug/pprof/profile后,默认需要等30s才会显示交互

top指令排序展示

在这里插入图片描述

每一行表示一个函数的信息,列信息字段解释:

  • flat:函数在 CPU 上运行的时间
  • flat%:函数在CPU上运行时间的百分比
  • sum%:是从第一行到当前行所有函数累加使用 CPU 的比例,如第二行sum=53.85=30.77+23.08
  • cum:这个函数以及子函数运行所占用的时间,应该大于等于flat
  • cum%:这个函数以及子函数运行所占用的比例,应该大于等于flat%
  • 最后一列:函数的名字

web指令生成图示

在交互模式下输入 web,会自动生成一个 svg 文件,并跳转到浏览器打开。

改功能需要安装graphviz后才能使用,安装方法https://shidawuhen.github.io/2020/02/08/go-callvis/ 。

调用链
图中每个方框对应应用程序运行的一个函数,方框越大代表函数执行的时间越久(函数执行时间会包含它调用的子函数的执行时间,但并不是正比的关系);方框之间的箭头代表着调用关系,箭头上的数字代表被调用函数的执行时间。

具体细节可以参考:https://github.com/google/pprof/tree/master/doc#interpreting-the-callgraph

runtime netpoll为例:
箭头上的230ms表示该函数总共的执行时间,包含自身和下游所有子节点;
方框中的10ms表示自身的执行时间;
方框中的2.70%表示自身执行时间在该函数总共执行时间的占比在总时间中的占比:2.70 = (10/230)*62.16
方框中的62.16%表示总时间占比,即整个程序耗时占比。

list指令分析函数

确定出哪个函数耗时之后,可以用pprof分析函数中的哪一行导致的耗时,使用子命令:list 函数名。
在这里插入图片描述

堆内存分析示例

内存分配既可以发生在堆上也可以在栈上。堆上分配的内存需要垃圾回收或者手动回收(对于没有垃圾回收的语言,例如 C++),栈上的内存则通常在函数退出后自动释放。

Go 语言通过逃逸分析会将尽可能多的对象分配到栈上,以使程序可以运行地更快。

这里说明一下,有两种内存分析策略:一种是当前的(这一次采集)内存或对象的分配,称为 inuse;另一种是从程序运行到现在所有的内存分配,不管是否已经被 gc 过了,称为 alloc

As mentioned above, there are two main memory analysis strategies with pprof. One is around looking at the current allocations (bytes or object count), called inuse. The other is looking at all the allocated bytes or object count throughout the run-time of the program, called alloc. This means regardless if it was gc-ed, a summation of everything sampled.

加上 -sample_index 参数后,可以切换内存分析的类型:
go tool pprof -sample_index=alloc_space http://localhost:8080/debug/pprof/heap
或者
go tool pprof -alloc_space http://localhost:8080/debug/pprof/heap

四种标签:
在这里插入图片描述


四、pprof数据分析类型汇总

其他数据的分析和CPU的基本一致。下面列举所有的分类:

http://localhost:8080/debug/pprof/ :获取概况信息,即本文第一张图的信息
go tool pprof http://localhost:8080/debug/pprof/allocs : 分析内存分配
go tool pprof http://localhost:8080/debug/pprof/block : 分析堆栈跟踪导致阻塞的同步原语
go tool pprof http://localhost:8080/debug/pprof/cmdline : 分析命令行调用的程序,web下调用报错
go tool pprof http://localhost:8080/debug/pprof/goroutine : 分析当前 goroutine 的堆栈信息
go tool pprof http://localhost:8080/debug/pprof/heap : 分析当前活动对象内存分配
go tool pprof http://localhost:8080/debug/pprof/mutex : 分析堆栈跟踪竞争状态互斥锁的持有者
go tool pprof http://localhost:8080/debug/pprof/profile : 分析一定持续时间内CPU的使用情况
go tool pprof http://localhost:8080/debug/pprof/threadcreate : 分析堆栈跟踪系统新线程的创建
go tool pprof http://localhost:8080/debug/pprof/trace : 分析追踪当前程序的执行状况

参考连接

  1. 一文搞懂pprof
  2. 深度解密Go语言之 pprof
  3. go性能分析工具pprof
  4. Go语言:利用pprof工具排查内存泄漏的示例
  5. Go语言:利用pprof工具查找goroutine(协程)泄漏的示例
  6. go 程序性能调优 pprof 的使用
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/sinat_24985411/article/details/128816228

智能推荐

【计算机毕业设计】189电商平台-程序员宅基地

文章浏览阅读80次。如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统商品交易信息管理难度大,容错率低,管理人员处理数据费工费时,所以专门为解决这个难题开发了一个电商平台,可以解决许多问题。电商平台可以实现商家管理,商品订单管理,用户管理,商品管理,商品评价管理等功能。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。电商平台可以提高商品交易信息管理问题的解决效率,优化商品交

js处理xml文件,成execl格式_js浏览器环境excel转xml-程序员宅基地

文章浏览阅读344次。nginx配置映射,js读取xml文件,整理成规整excel格式的字符传_js浏览器环境excel转xml

springboot整合jett实现模板excel数据导出_spring boot 导出模板数据-程序员宅基地

文章浏览阅读648次。jett是使用Excel电子表格模板快速创建Excel电子表格报告的工具。_spring boot 导出模板数据

vmstat命令详解-程序员宅基地

文章浏览阅读231次。基础命令学习目录首页原文链接:https://www.cnblogs.com/wensiyang0916/p/6514820.htmlvmstat 1 1表示每秒采集一次vmstat 2 1 2表示2秒采集一次,1表示只采集一次r 表示运行队列(就是说多少个进程真的分配到CPU) 我测试的服务器目前CPU比较空闲,没什么程序在跑,当这个值..._vmstat 1 2

无源波分和彩光模块_无源波分技术及其在4G/5G前传中的应用-程序员宅基地

文章浏览阅读413次。1、无源波分前传方案简述无源波分采用WDM技术,将BBU/DU至不同RRU/AAU的电路采用不同的波长合路到一根光纤中传输。例如,一个4G宏站某个频段的S111站共3个RRU,BBU至RRU的收发端口数共6个,在BBU侧和RRU侧各采用1个6路的OTM(光终端复用器)就可以将BBU和RRU间的收发信号合路到一根光纤中传输,如图1所示。图1 无源WDM前传方案由于OTM是无源器件,故各业务端口光模块..._彩光模块 光纤 发射部分 bbu 波长较大

建边——邻接矩阵、vector、链式向前星_邻接矩阵4vector-程序员宅基地

文章浏览阅读635次。## 建边(图论的中一般都会牵涉到建边的问题,下面的这三种建边的方法视情况选取) - **1.1—邻接矩阵** ==**用邻接矩阵建边的时候,注意题目中可能会有重边!重边!重边!!!**==(根据情况选短的或长的那条),后面两种方法应该不会受重边的影响(目前还没有遇到过有影响的)```cint main(){ int sx,ex,len; //n个点,m条边 while(scanf("%d%d",&n,&m)!=EOF) { _邻接矩阵4vector

随便推点

“要接单“平台:打造技术侠的专属舞台,保障权益,共创美好未来-程序员宅基地

文章浏览阅读301次。一上来就谈钱,或许显得有些直白,但在我们这一行,明确的收费方式是对双方最基本的尊重。这里,不仅汇聚了各行各业的项目需求,更有一套完善的收费机制,确保你的每一份付出都值得尊重。在这里,你不仅能找到适合自己的项目,还能与同行交流,共同成长。记住,没有需求文档的项目,十有八九是个坑。在要接单平台,我们严格把关项目发布的真实性和可行性,让每一位技术侠都能在明确需求的情况下,安心接单。项目细分:无论是简单还是复杂的任务,我们都将其细分到最小单元,确保每位接单者都能按自己的能力和兴趣挑选项目。你的成果,值得被尊重。

史上最全的Android开发学习教程集锦【初学者】_android 项目学习-程序员宅基地

文章浏览阅读5.3w次,点赞39次,收藏399次。根据Google的报告,截止2017年5月为止,Android活跃用户已超过20亿,并还在持续增长中。Android系统在几个主要的市场上已超过了iOS系统,特别是在美国,欧洲和日本,然而苹果确实在中国市场找到了一席之地。未来的市场到底谁是“霸主”我们还无从得知,但Android现在的趋势已经超过iOS。这也是为什么越来越多的设计师投身于Android开发设计。本篇文章从不同角度给Android开..._android 项目学习

揭秘: 优秀CIO的OA选型标准_fanweioa-程序员宅基地

文章浏览阅读6.8k次。OA选型一直是企业信息化建设面临的难题,企业内部没有人懂OA系统,OA行业也没有什么权威机构和数据可以参考,OA系统厂商排名纯属自嗨,那么,到底该如何进行OA选型?看成功企业的选型标准!这些企业CIO在选型时积累的经验都具有极高参考价值,他们的OA选型标准就是你的OA选型指南。OA选型1、综合实力人员:完整的团队是OA项目实施落地的保障,对于企业OA选型来说至关重要,也是企业CIO主要考量标准之一..._fanweioa

Apache Ranger0.5编译-程序员宅基地

文章浏览阅读22次。1. 编译环境# CentOS7# java git gcc环境yum install git wget yum java-1.8.0-openjdk* gcc -y# maven环境wget https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin...

SpringMVC基础掌握--一图看懂三大处理器以及执行流程_springmvc处理器-程序员宅基地

文章浏览阅读1k次,点赞29次,收藏27次。Spring MVC所有的请求都经过Dispatcherservlet来统一分发。DispatcherServlet将请求分发给Controller之前,需要借助于Spring MVC提供的HandlerMapping定位到具体的Controller。HandlerMapping接口负责完成客户请求到Controller映射。Controllr接口将处理用户情求,这和Java Servlet扮演的角色是一致的。_springmvc处理器

ES6 模块暴露_es6暴露模块-程序员宅基地

文章浏览阅读31次。ES6 模块暴露。_es6暴露模块

推荐文章

热门文章

相关标签