一、简单使用
代码引入net/http/pprof:
package main
import (
"fmt"
"net/http"
_ "net/http/pprof"
)
func main() {
go func() {
fmt.Println(http.ListenAndServe(":9192", nil))
}()
}
编译启动后,通过页面访问:
http://192.168.137.2:9192/debug/pprof/
分为以下项目:
Profile Descriptions:
-
allocs:
A sampling of all past memory allocations -
block:
Stack traces that led to blocking on synchronization primitives -
cmdline:
The command line invocation of the current program -
goroutine:
Stack traces of all current goroutines. Use debug=2 as a query parameter to export in the same format as an unrecovered panic. -
heap:
A sampling of memory allocations of live objects. You can specify the gc GET parameter to run GC before taking the heap sample. -
mutex:
Stack traces of holders of contended mutexes -
profile:
CPU profile. You can specify the duration in the seconds GET parameter. After you get the profile file, use the go tool pprof command to investigate the profile. -
threadcreate:
Stack traces that led to the creation of new OS threads -
trace:
A trace of execution of the current program. You can specify the duration in the seconds GET parameter. After you get the trace file, use the go tool trace command to investigate the trace.
但是此种方式查看不够直观,可以通过go tool pprof工具生成动态图像查看:
yum install graphviz
查看内存分配:
go tool pprof -http=192.168.137.2:8000 http://127.0.0.1:9192/debug/pprof/allocs
查看CPU占用:
go tool pprof -http=192.168.137.2:8000 http://127.0.0.1:9192/debug/pprof/profile
本机防火墙开放8000端口,通过页面访问:
firewall-cmd --add-port=8000/tcp --permanent
firewall-cmd --reload
http://192.168.137.2:8000/ui/
二、pprof的采样过程和原理
pprof是什么?
在 Go 语言中,pprof 是用于可视化和分析性能分析数据的工具,pprof 以 profile.proto 读取分析样本的集合,并生成报告以可视化并帮助分析数据(支持文本和图形报告)。
而刚刚提到的 profile.proto 是一个 Protobuf v3 的描述文件,它描述了一组 callstack 和 symbolization 信息, 作用是统计分析的一组采样的调用栈,是很常见的 stacktrace 配置文件格式。
一句话描述:Golang自带的一款开箱即用的性能监控和分析工具。
pprof的作用
go的pprof提供了2个工具供我们使用,runtime/pprof中是它的源码,net/http/pprof对源码做了简单封装,能让你在http服务中直接使用。
它可以采样程序运行时的CPU、堆内存、Goroutine、锁竞争、阻塞调用、系统线程的使用情况。然后通过可视化终端或网页的形式展示给用户,用户可以通过列表、调用图、源码、火焰图、反汇编等视图去展示采集到的性能指标。
pprof指标采样的维度
-
CPU(profile)
- CPU Profiling:CPU 分析,按照一定的频率采集所监听的应用程序 CPU(含寄存器)的使用情况,可确定应用程序在主动消耗 CPU 周期时花费时间的位置。
- 报告CPU的使用情况,定位到热点(消耗CPU周期最多的)代码。默认情况下Go以100HZ的频率进行CPU采样
-
Goroutine
- Goroutine Profiling: Goroutine 分析,可以对当前应用程序正在运行的 Goroutine 进行堆栈跟踪和分析。这项功能在实际排查中会经常用到,因为很多问题出现时的表象就是 Goroutine 暴增,而这时候我们要做的事情之一就是查看应用程序中的 Goroutine 正在做什么事情,因为什么阻塞了,然后再进行下一步。
-
系统线程
- 获取导致创建 OS 线程的 goroutine 堆栈
-
堆内存/内存剖析(heap)
- Memory Profiling:内存分析,在应用程序进行堆分配时记录堆栈跟踪,用于监视当前和历史内存使用情况,以及检查内存泄漏。
- 包含每个 goroutine 分配大小,分配堆栈等。
- 每分配 runtime.MemProfileRate(默认为512K) 个字节进行一次数据采样。
-
内存剖析(allocs):报告所有内存分配历史
-
阻塞操作
- Block Profiling:阻塞分析,记录 Goroutine 阻塞等待同步(包括定时器通道)的位置,默认不开启,需要调用
runtime.SetBlockProfileRate
进行设置。 - 获取导致阻塞的 goroutine 堆栈(如 channel, mutex 等),使用前需要先调用
runtime.SetBlockProfileRate
- Block Profiling:阻塞分析,记录 Goroutine 阻塞等待同步(包括定时器通道)的位置,默认不开启,需要调用
-
锁竞争
- Mutex Profiling:互斥锁分析,报告互斥锁的竞争情况,默认不开启,需要调用
runtime.SetMutexProfileFraction
进行设置。
- Mutex Profiling:互斥锁分析,报告互斥锁的竞争情况,默认不开启,需要调用
-
执行追踪(trace):追踪当前应用程序的执行栈
pprof的原理
1 CPU采样
CPU采样会记录所有的调用栈和它们的占用时间。
在采样时,进程会每秒暂停一百次,每次会记录当前的调用栈信息。
汇总之后,根据调用栈在采样中出现的次数来推断函数的运行时间。 你需要手动地启动和停止采样。每秒100次的暂停频率也不能更改。
这个定时暂停机制在unix或类unix系统上是依赖信号机制实现的。
每次「暂停」都会接收到一个信号,通过系统计时器来保证这个信号是固定频率发送的。 接下来看看具体的流程。
一共有三个相关角色:进程本身、操作系统和写缓冲。
启动采样时,进程向OS注册一个定时器,OS会每隔10ms向进程发送一个SIGPROF信号,进程接收到信号后就会对当前的调用栈进行记录。
与此同时,进程会启动一个写缓冲的goroutine,它会每隔100ms从进程中读取已经记录的堆栈信息,并写入到输出流。
当采样停止时,进程向OS取消定时器,不再接收信号,写缓冲读取不到新的堆栈时,结束输出。
采样对象:函数调用和它们的占用时间
采样率:100次/秒
固定值采样时间:从手动启动到手动结束