go tool pprof 参数 ‘-base‘ 和 ‘-diff_base‘ 之间的区别

news2025/1/9 1:06:52

go tool pprof 工具是用于分析由 runtime/pprof包 或 net/http/pprof包产生的profile数据,完整的帮助文档在 https://github.com/google/pprof/blob/main/doc/README.md ,pprof 工具支持的参数很多,可以用命令 go tool pprof --help来查看全部参数列表,今天主要来说下 -base-diff_base 这两个参数, 因为文档对这两个参数的描述比较晦涩,难以理解这两个参数之间的区别。

    -diff_base source     Source of base profile for comparison
    -base source          Source of base profile for profile subtraction

pprof can subtract one profile from another, provided the profiles are of compatible types (i.e. two heap profiles). pprof has two options which can be used to specify the filename or URL for a profile to be subtracted from the source profile:
 
-diff_base= profile: useful for comparing two profiles. Percentages in the output are relative to the total of samples in the diff base profile.
 
-base= profile: useful for subtracting a cumulative profile, like a golang block profile, from another cumulative profile collected from the same program at a later time. When comparing cumulative profiles collected on the same program, percentages in the output are relative to the difference between the total for the source profile and the total for the base profile.
 
The -normalize flag can be used when a base profile is specified with either the -diff_base or the -base option. This flag scales the source profile so that the total of samples in the source profile is equal to the total of samples in the base profile prior to subtracting the base profile from the source profile. Useful for determining the relative differences between profiles, for example, which profile has a larger percentage of CPU time used in a particular function.
 
When using the -diff_base option, some report entries may have negative values. If the merged profile is output as a protocol buffer, all samples in the diff base profile will have a label with the key “pprof::base” and a value of “true”. If pprof is then used to look at the merged profile, it will behave as if separate source and base profiles were passed in.
 
When using the -base option to subtract one cumulative profile from another collected on the same program at a later time, percentages will be relative to the difference between the total for the source profile and the total for the base profile, and all values will be positive. In the general case, some report entries may have negative values and percentages will be relative to the total of the absolute value of all samples when aggregated at the address level.

这两个参数都是用于多个profile文件之间的对比,文档中关于这两个参数的描述翻译过来:

比较profile文件

pprof 工具可以从一个profile文件中减去另一个profile文件,前提是这两个profile文件类型是兼容的(比如两个都是heap profile文件)。pprof有两个选项,用于指定需要减去的这个profile文件的文件名或URL:
 
-diff_base=profile:用于比较两个profile文件。计算出的百分比是基于diff_base 参数指定的这个profile文件中的采样指标之和。
 
-base=profile:用于累计指标类型的profile文件(比如golang的block profile),适用于将同一个程序后采集的profile文件减去先采集的profile文件的场景。当对比在同一个程序上收集的累计指标类型的profile文件时,展示的百分比是基于当前采集的profile文件中的采样指标之和与之前采集的profile文件中采样指标之和之间的差值
 
当用-diff_base-base参数指定基准profile文件时,可以加上-normalize 选项,加上该选项后,在计算当前profile文件与基准profile文件的采样和差值之前,会把当前profile文件的采样数据全部乘以一个固定的百分比(用基准profile采样和除以当前profile采样和得到),使得当前profile的采样数据之和与基准profile采样和相等。通常用于确定两个profile文件之间的相对差异,例如,用于比较哪个profile在特定函数中消耗的CPU时间占比更高。
 
当使用-diff_base选项时,某些指标可能会存在负值。如果合并后的profile文件以protocol buffer 格式输出,则基准profile文件中的所有采样都会加上pprof::base的Label,Label的值为“true”。如果随后使用pprof工具来查看合并之后的profile文件,那么它的表现和同时传入合并前的原始profile文件和基准profile文件保持一致。
 
当使用-base选项从同一个程序上后收集的一个累计指标类型的profile文件中减去一个之前收集的同类型的profile文件时,百分比将相对于后收集的profile文件的采样指标总和与先收集的profile文件的采样指标总和之间的差值,并且所有值都将为正数(因为累计指标是随着时间在不断增长的,后采集的值不会比先采集的值要小)。一般来说,有些指标可能会存在负值,这时当在地址级别进行聚合时,百分比将相对于所有采样指标的绝对值之和。

总结下来就是,两个参数都是用于计算当前 profile文件减去基准profile文件所获得的差值,用这个差值生成一个新的profile文件,区别在于计算这个新生成的profile文件每个采样指标的占比时,-base 是基于基准profile文件的指标和(所以百分比可能大于100%),而 -diff_base 则是基于差值profile文件的指标和(也就是这个新生成的profile文件本身的指标和,所以每个采样的指标占比不会超过100%)。

比如我这里由同一个程序前后生成了两个profile文件: profile001.pb.gzprofile002.pb.gz,现在分别用 -base-diff_base 参数生成一个差集profile:

$ pprof -proto -output gen_by_base_opt.pb.gz -base profile001.pb.gz profile002.pb.gz
Generating report in gen_by_base_opt.pb.gz
$ pprof -proto -output gen_by_diff_base_opt.pb.gz -diff_base profile001.pb.gz profile002.pb.gz
Generating report in gen_by_diff_base_opt.pb.gz
$ ll
total 48
-rw-r--r--  1 zy  staff  2839  5 18 19:42 gen_by_base_opt.pb.gz
-rw-r--r--  1 zy  staff  4772  5 18 19:42 gen_by_diff_base_opt.pb.gz
-rw-r--r--  1 zy  staff  3092  5 17 16:43 profile001.pb.gz
-rw-r--r--  1 zy  staff  4504  5 17 16:59 profile002.pb.gz

分别计算出这两个差集的指标和:

package main

import (
	"fmt"
	"github.com/google/pprof/profile"
	"log"
	"os"
)

func sumProfile(file string) map[string]int64 {
	f, err := os.Open(file)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()
	pprof, err := profile.Parse(f)
	if err != nil {
		log.Fatal(err)
	}
	sums := make(map[string]int64, len(pprof.SampleType))

	for _, sample := range pprof.Sample {
		for i, v := range sample.Value {
			sums[pprof.SampleType[i].Type] += v
		}
	}
	return sums
}

func main() {
	var sum map[string]int64

	sum = sumProfile("./profile001.pb.gz")
	fmt.Println("sum of profile001.pb.gz: ")

	keys := make([]string, 0, len(sum))
	for k := range sum {
		keys = append(keys, k)
	}

	for _, k := range keys {
		fmt.Println(k, " --> ", sum[k])
	}
	fmt.Println()

	sum = sumProfile("./profile002.pb.gz")
	fmt.Println("sum of profile002.pb.gz: ")
	for _, k := range keys {
		fmt.Println(k, " --> ", sum[k])
	}
	fmt.Println()

	sum = sumProfile("./gen_by_base_opt.pb.gz")
	fmt.Println("sum of gen_by_base_opt.pb.gz: ")
	for _, k := range keys {
		fmt.Println(k, " --> ", sum[k])
	}
	fmt.Println()

	sum = sumProfile("./gen_by_diff_base_opt.pb.gz")
	fmt.Println("sum of gen_by_diff_base_opt.pb.gz: ")
	for _, k := range keys {
		fmt.Println(k, " --> ", sum[k])
	}
	fmt.Println()
}


执行结果:

sum of profile001.pb.gz: 
alloc_objects  -->  26137
alloc_space  -->  31409035
inuse_objects  -->  3914
inuse_space  -->  3148768

sum of profile002.pb.gz: 
alloc_space  -->  98663649
inuse_objects  -->  9397
inuse_space  -->  4771620
alloc_objects  -->  51635

sum of gen_by_base_opt.pb.gz: 
alloc_objects  -->  25498
alloc_space  -->  67254614
inuse_objects  -->  5483
inuse_space  -->  1622852

sum of gen_by_diff_base_opt.pb.gz: 
alloc_objects  -->  25498
alloc_space  -->  67254614
inuse_objects  -->  5483
inuse_space  -->  1622852

可以看出,gen_by_base_opt.pb.gzgen_by_diff_base_opt.pb.gz 的各项指标和等于 profile002.pb.gz 值减去 profile001.pb.gz

通过 pprof 工具来查看生成的差集profile:

$ pprof -http=: -base=profile001.pb.gz profile002.pb.gz
Serving web UI on http://localhost:57739

在这里插入图片描述

$ pprof -http=: -diff_base=profile001.pb.gz profile002.pb.gz
Serving web UI on http://localhost:57845

在这里插入图片描述
对比两幅火焰图可以看出两幅图除了百分比之外基本没有差别,并且从右上角可以看出这里展示的是 alloc_space指标数据,而 64.14MB 正好就是我们上面生成的profile文件gen_by_base_opt.pb.gzgen_by_diff_base_opt.pb.gzalloc_space指标和(67254614 / 1024 / 1024 = 64.13899803161621)。

而百分比之所以不同,是因为计算百分比的基数不同,-base 是以计算出的差集本身作为基准值计算百分比,而-diff_base则是以指定的base profile,也就是这里的 profile001.pb.gz 指标值作为基准进行计算 ( 67254614 / 31409035 = 2.141250566914902)。

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

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

相关文章

DJ5-4 交换局域网(第一节课)

目录 一、局域网概述 1、LAN 的特点和分类 2、常见的网络拓扑结构 二、计算机与局域网的连接 三、局域网体系结构 四、链路层寻址地址 1、MAC 地址分配 2、MAC 地址识别 五、ARP 地址解析协议 1、ARP 地址解析协议 2、ARP:两个主机位于同一个局域网 3、…

网络计算模式复习(六)

什么是CDN CDN的全称是Content Delivery Network,即内容分发网络。 其目的通过在现有的Internet中增加一层新的网络架构,将网站的内容发布到最接近用户的网络“边缘”,使用户可以就近取得所需的内容,解决Internet网络拥挤的状况&…

socket套接字通信 TCP传输控制协议/IP网络协议 5.18

B/S :浏览器和服务器 C/S :客户机和服务器 网络的体系结构: 网络的层次结构和每层所使用协议的集合 网络采用分层管理的方法,将网络的功能划分为不同的模块 OSI模型: 共7种: 应用层:接收用户的数据,面…

Blender基础技巧小结(三)

本文续签一篇:Blender基础技巧小结(二)_皮尔斯巴巴罗的博客-CSDN博客 将物体显示为模板,类似Maya Template 四窗口视图 调整3d视图远截面 Blender并不直接支持放样,可以用第三方插件,但效果并不好 基于me…

usb摄像头驱动打印信息

usb摄像头驱动打印信息 文章目录 usb摄像头驱动打印信息 在ubuntu中接入罗技c920摄像头打印的信息如下: [ 100.873222] usb 3-2: new high-speed USB device number 5 using xhci_hcd [ 101.230728] usb 3-2: New USB device found, idVendor046d, idProduct08e5 …

SpringMVC的拦截器(Interceptor)

文章目录 1 拦截器概念2 拦截器入门案例2.1 环境准备2.2 拦截器开发步骤1:创建拦截器类步骤2:配置拦截器类步骤3:SpringMVC添加SpringMvcSupport包扫描步骤4:运行程序测试步骤5:修改拦截器拦截规则步骤6:简化SpringMvcSupport的编写 3 拦截器参数3.1 前置处理方法3.2 后置处理方…

使用frp进行内网穿透(远程连接内网服务器)

文章目录 云服务购买服务器端(即我们购买的服务器)配置客户端(即我们自己的服务器)配置使用xshell登录远程服务器在服务器端设置frp开机自启动在客户端设置frp开机自启动 这里主要介绍使用frp工具进行内网穿透,适合的场…

Spring6和SpringBoot3的新特性-你不得不了解的AOT原来这么简单

Spring6.0新特性 一、Spring的发展历史 二、AOT AOT是Spring6.0提供的一个新特性,Ahead of Time 提前编译。 1.AOT概述 1.1 JIT和AOT的关系 1.1.1 JIT JIT(Just-in-time) 动态编译,即时编译,也就是边运行边编译,也就是在程序运…

LangChain与大型语言模型(LLMs)应用基础教程:角色定义

如果您还没有看过我之前写的两篇博客,请先看一下,这样有助于对本文的理解: LangChain与大型语言模型(LLMs)应用基础教程:Prompt模板 LangChain与大型语言模型(LLMs)应用基础教程:信息抽取 LangChain是大型语言模型(LLM)的应用框架,LangCha…

RK3568平台开发系列讲解(LCD篇)快速了解RK LCD的使用

🚀返回专栏总目录 文章目录 一、内核Config配置二、MIPI配置2.1 引脚配置2.2 背光配置2.3 显示时序配置2.3.1 Power on/off sequence2.3.2 Display-Timings三、EDP配置3.1 引脚配置3.2 EDP背光配置沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 本篇章带大家快速了…

数据结构_查找

目录 1. 查找的基本概念 2. 顺序查找和折半查找 2.1 顺序查找 2.1.1 一般线性表的顺序查找 2.1.2 有序表的顺序查找 2.2 折半查找 2.3 分块查找 2.4 相关练习 3. 树型查找 3.1 二叉排序树 3.1.1 二叉排序树的定义 3.1.2 二叉排序树的查找 3.1.3 二叉排序树…

想要一个本地部署的海洋实景三维展示系统吗?

最近几年实景三维非常火,很多人包括博主都想将自己平时干的海洋测绘项目进行实景三维化,这样做的好处就是无论是管理数据还是成果展示都非常方便。我们可能会使用谷歌地图、奥维地图、图新地球等地图服务软件,它们也提供了一些测量、画图功和…

使用Hexo在Github上搭建个人博客

使用Hexo在Github上搭建个人博客 1. 安装Node和git2. 安装Hexo3. Git与Github的准备工作4. 将Hexo部署到Github5. 开始写作 1. 安装Node和git 在Mac上安装Node.js可以使用Homebrew,使用以下命令安装: brew install node使用以下命令安装Git: …

解决 Uncaught TypeError: SpriteCanvasMaterial is not a constructor.

文章目录 前言一、替代语法总结 前言 上周买了本《Three.js开发指南》, 第三版, 里面的语法不太跟趟, 有点旧, 倒也不能全怪作者, three迭代的确很快. 一、替代语法 这几天没事做, 加上前面本来就接触过Three, 很快进展到了第六章. 在推进 利用Canvas贴图给精灵(Sprite)增加样…

研发工程师玩转Kubernetes——启用microk8s的监控面板(dashboard)

安装插件 microk8s enable dashboard 查看dashboard 地址 由于dashboard是在kube-system的namespace中,我们可以使用下面指令查看它服务的地址。 microk8s kubectl get service -n kube-system kubernetes-dashboard 可以得到地址是https://10.152.183.167。 登…

Android Jetpack-Databinding基本使用

文章目录 让你的项目支持Databinding基本使用布局和绑定表达式常用运算符判空null获取对象属性避免空指针异常其他控件引用资源引用 事件处理import,variables,and includesimportVariablesIncludes 数据更新->UI更新监听字段变化更新监听对象变化更新 UI更新->数据更新绑…

MPLS隧道——隧道迭代与MPLS高可靠性

目录 MPLS隧道迭代 什么情况下需要隧道迭代 解决方法 MPLS高可靠性 VPN FRR VPN GR MPLS隧道迭代 什么情况下需要隧道迭代 解决方法 两种解决方法 将IBGP邻居更改为Vpnv4的IBGP邻居(为目标网段产生私网标签,然后此带标签的BGP路由直接进入标签隧道…

作为程序员的你,常用的工具软件有哪些?

不会还有程序员没用过Chatgpt吧? 我现在的工作日常:把需求提给Chatgpt,代码出来后再自行润色一下代码,然后到工业环境里跑一下,没问题就可以提交了。一来一回效率提高了好几倍,摸鱼的时间都变多了…… 除了…

自学黑客(网络安全)必学内容

随着时代的发展,经济、社会、生产、生活越来越依赖网络。而随着万物互联的物联网技术的兴起,线上线下已经打通,虚拟世界和现实世界的边界正变得模糊。这使得来自网络空间的攻击能够穿透虚拟世界的边界,直接影响现实世界的安全。 …

环环相扣,循环不止:深入解析循环队列

本盘博客会讲解力扣“622. 设计循环队列”的解题思路,这是题目链接。 先来审下题: 以下是示例: 以下是提示: 如何设计一个循环队列呢?这里我用数组来实现。结构的定义如下: typedef struct {int* a; …