Go pprof 认知到实践

news/2024/10/4 5:29:13

快速开始

测试环境:go version go1.22.2 windows/amd64,源代码开源在 https://github.com/oldme-git/teach-study/tree/master/golang/base/pprof

在正式开始之前,请确保安装 graphviz,这一步不可省略,它可以协助 pprof 生成更直观的数据分析图。可以参考官方网站的安装方法。

go 使用 runtime/pprof 包来对程序进行采样,当然,还有另外一个包 net/http/pprof,这里先按下不表。先来看一个 CPU 分析的例子:

package mainimport ("math""math/rand""os""runtime/pprof"
)func main() {// 保存 CPU 采样数据file := "cpu.pprof"os.Remove(file)f, err := os.OpenFile(file, os.O_CREATE|os.O_RDWR, 0644)if err != nil {panic(err)}defer f.Close()// 开始采样err = pprof.StartCPUProfile(f)if err != nil {panic(err)}defer pprof.StopCPUProfile()// 测试程序for i := 0; i < 1000; i++ {nums := genRandomNumbers(10000)for _, v := range nums {_ = math.Pow(float64(v), rand.Float64())}}
}// 测试程序,生成一个随机数切片
func genRandomNumbers(n int) []int {nums := make([]int, n)for i := 1; i < n; i++ {nums[i] = rand.Int() * n}return nums
}

这是一个很简单的例子,运行 go run main.go 在当前目录下生成一个 cpu.pprof 文件。然后输入命令 go tool pprof cpu.pprof 进入 pprof 的命令行中。

PS D:\project\teach-study\golang\base\pprof\cpu> go run  main.go        
PS D:\project\teach-study\golang\base\pprof\cpu> go tool pprof cpu.pprof
File: main.exe
Build ID: C:\Users\half\AppData\Local\Temp\go-build787417447\b001\exe\main.exe2024-05-08 11:13:12.7105156 +0800 CST
Type: cpu
Time: May 8, 2024 at 11:13am (CST)
Duration: 1.26s, Total samples = 1.07s (85.20%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof)

pprof 命令有很多,可以输入 help 查看,不过一般常用的就两个: topweb。输入 top5 可以查看前 5 的耗时调用。

// 输入
top5// 输出
Showing nodes accounting for 700ms, 65.42% of 1070ms total
Showing top 5 nodes out of 69flat  flat%   sum%        cum   cum%210ms 19.63% 19.63%      210ms 19.63%  math.archLog180ms 16.82% 36.45%      180ms 16.82%  math.archExp160ms 14.95% 51.40%      670ms 62.62%  math.pow80ms  7.48% 58.88%       80ms  7.48%  internal/chacha8rand.block70ms  6.54% 65.42%       70ms  6.54%  math/rand.globalRand

来认识一下这五个指标:

flat 是我们最关注的指标,它代表自身耗时,不包含内部调用。
falt% 自身耗时相对于总耗时的百分比
cum 自身耗时加上内部函数调用的总耗时
cum% 自身耗时加上内部函数调用的总耗时相对于总耗时的百分比
sum% 前 N 行的 flat% 之和。对于上述例子的第四行 58.88=19.63+16.82+14.95+7.48

只是依赖文字无法很好的理解这些指标,我们可以使用 web 命令来生成更直观的 svg 分析图。输入 web 命令后,会自动在浏览器打开 svg

svg 中的每个单元格包含了包名,函数名,flat, flat%, cum, cum%

单元格颜色越红,代表 cum 越大,反之越小;单元格越大,代表 flat 越大,反之越小。单元格之间的箭头线代表调用链,线越粗代表消耗的更多的资源,反之亦然。带有 inline 字段表示该函数被内联进了调用方(当作普通线处理就行)。

函数调用是存在一些固定开销的,例如维护帧指针寄存器BP、栈溢出检测等。因此,对于一些代码行比较少的函数,编译器倾向于将它们在编译期展开从而消除函数调用,这种行为就是内联。

更多的 Web UI

通过 web 命令已经可以获取很直观的性能分析图,我们还可以使用 -http 参数来启用一个 web 服务,获取更多的性能分析。输入 exit 退出 pprof 命令界面,输入命令:

go tool pprof -http=:7000 cpu.pprof

之后会自动在浏览器打开 http://localhost:7000/ui/

view 中可以使用火焰图(Flame Graph),火焰图有新旧两种,可以根据线的长短和颜色判断 CPU 耗时。其他的选项可以点点看看,不复杂,很容易就学会了。

web 服务采样

对于 web 服务的 pprof 采样,我们可以使用基于 runtime/pprof 封装的更便捷的 net/http/pprof 包。

package mainimport ("fmt""math""math/rand""net/http"_ "net/http/pprof"
)func main() {http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {// 测试程序for i := 0; i < 1000; i++ {nums := genRandomNumbers(10000)for _, v := range nums {_ = math.Pow(float64(v), rand.Float64())}}fmt.Fprint(w, "Hello, world!")})http.ListenAndServe(":8080", nil)
}// 测试程序,生成一个随机数切片
func genRandomNumbers(n int) []int {nums := make([]int, n)for i := 1; i < n; i++ {nums[i] = rand.Int() * n}return nums
}

打开 http://127.0.0.1:8080/debug/pprof/ ,可以看到 pprof  的实时采样数据:

这里面一共有九个采样数据:

allocs 查看历史累计的所有内存分配的采样数据
block 查看历史累计的导致同步原语阻塞的堆栈跟踪
cmdline 包含进程的完整命令行信息,通常用于记录程序启动时的命令行参数
goroutine 实时查看当前所有运行的 goroutines 堆栈跟踪
heap 实时查看活动对象的内存分配情况
mutex 查看历史累计的导致互斥锁的竞争持有者的堆栈跟踪
profile 进行 30s 的 CPU Profiling,浏览器会转圈,30s 后下载一个分析用的 profile 文件
threadcreate 查看创建新 OS 线程的堆栈跟踪
trace 程序执行 trace, 和其他样本数据不同的是,这个需要使用 go tool trace 来分析。trace 是一种更详细的性能分析工具,用于跟踪程序的执行过程,包括函数调用、协程切换等。

默认是不追踪 blockmutex 的,如果需要,在代码中加入这两个:

runtime.SetBlockProfileRate(1) // 开启 block  
runtime.SetMutexProfileFraction(1) // 开启 mutex

这些信息都是实时变化的,刷新一下浏览器即可看见,但是这些信息不易阅读,我们可以把它们下载下来,使用 pprof 分析,以 allocs 为例:

// 下载 allocs 数据
curl -o allocs.pprof http://localhost:8080/debug/pprof/allocs
// pprof
go tool pprof .\allocs.pprof

非 Web 程序的其他采样

在快速开始部分已经介绍了 CPU 采样,对于其他采样,可以参考这段代码:

package mainimport ("math""math/rand""os""runtime/pprof"
)func main() {// 保存 CPU 采样数据file := "allocs.pprof"os.Remove(file)f, err := os.OpenFile(file, os.O_CREATE|os.O_RDWR, 0644)if err != nil {panic(err)}defer f.Close()// 测试程序for i := 0; i < 1000; i++ {nums := genRandomNumbers(10000)for _, v := range nums {_ = math.Pow(float64(v), rand.Float64())}}pprof.Lookup("allocs").WriteTo(f, 0)
}// 测试程序,生成一个随机数切片
func genRandomNumbers(n int) []int {nums := make([]int, n)for i := 1; i < n; i++ {nums[i] = rand.Int() * n}return nums
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/29005.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

C#与PLC变量在数据交互上的一些探索

1. 基于C#的数据交互 A. S7,using S7.Net,后文读写数据时二次封装过S7协议,这里暂且不表,只列举S7协议最原始的应用。new一个PLC对象//idenfy basic link paramsprivate string plc_ip;private CpuType plc_type;private short plc_rack, plc_slot;public Plc my_plc;my_plc…

三角函数之诱导公式

壹如上图: \[\begin{eqnarray} 已知: \enspace AC=\sin\alpha,BC=\cos\alpha \\ \\ \\ \sin\left(\frac{\pi}{2}-\alpha\right)=\frac{AD}{AB}=\frac{BC}{AB}=\cos\alpha \\ \\ 诱导公式组0.1: \enspace \sin\left(\frac{\pi}{2}-\alpha\right)=\cos\alpha \\ \\ \\ \cos\left(…

ubuntu下多jdk环境轻松却换

在实际coding生活中,维护老项目与开发新项目常是并行的。快速企业java开发jdk版本,收首先要解决的问题。 今天看到一篇Blog,参考配置后完美实现了一键快速切换,nice!!!!!! 环境: 1、ubuntu 22 2、openjdk1.8、openjdk17 具体操作步骤: 1、安装openjdk(略),安装位…

CentOS 7 部署 NET6.0 项目过程

1、环境配置NET6.0 环境搭建主要是SDK 和 runtime 的安装,下图截自官网说明了SDK 和 runtime 的关系CentOS7 安装SDK 方法第一步:rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm第二部:yum install dotnet-sdk-6.0也可以只安装对应的…

细说夜莺监控系统告警自愈机制

虽说监控系统最侧重的功能是指标采集、存储、分析、告警,为了能够快速恢复故障,告警自愈机制也是需要重点投入建设的,所有可以固化为脚本的应急预案都可以使用告警自愈机制来快速驱动。夜莺开源项目从 v7 版本开始内置了告警自愈模块,本文将详细介绍告警自愈的原理和实现。…

程序员副业创富:业余时间解锁首笔财富里程碑

在这个充满机遇的数字时代,我,一个普通的程序猿,编程爱好者,终于在云端源想这个平台上收获了属于我的第一桶金。这是一个关于兼职、学习与成长的故事,希望能激发同在编程路上的你,勇敢迈出那一步。 先晒晒我的首笔收入:一个普通的周末,我像往常一样,泡上一杯咖啡,坐在…

(一)文本分类经典模型之CNN篇

这篇blog对NLP领域的基本任务文本分类的CNN经典模型做了梳理CNN源于计算机视觉研究,后来诸多学者将其应用于短文本分类,其基本结构如下图所示:由上图可知,基于CNN的短文本分类模型,通常包括输入层、卷积层、池化层、全连接层和输出层五部分,其中卷积层和池化层是最为关键…

Apache DolphinScheduler 3.3.0 版本重磅更新提前看!

Apache DolphinScheduler 3.3.0版本终于要在万众期待中发布啦!本次发版将有重大功能更新,包括架构上的调整。 为了让广大用户提前尝鲜,社区特别准备了直播活动提前揭秘3.3.0版本中的重要更新,到时候你将会了解到这些信息:3.3.0版本的工作流引擎改进 任务执行流程的优化 架…