go tool pprof 参数 '-base' 和 '-diff_base'之间的区别解析

 更新时间:2023年05月27日 10:35:49   作者:代码一天不写我浑森蓝廋  
这篇文章主要介绍了go tool pprof 参数 '-base' 和 '-diff_base'之间的区别,两个参数都是用于计算当前 profile文件减去基准profile文件所获得的差值,用这个差值生成一个新的profile文件,本文给大家介绍的非常详细,需要的朋友可以参考下

go tool pprof 工具是用于分析由 runtime/pprof包 或 net/http/pprof包产生的profile数据,完整的帮助文档在 https://github.com/google/pprof/blob/main/doc/README.mdpprof 工具支持的参数很多,可以用命令 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)。

到此这篇关于go tool pprof 参数 ‘-base‘ 和 ‘-diff_base‘ 之间的区别的文章就介绍到这了,更多相关go tool pprof 参数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于Go+WebSocket实现实时通信功能

    基于Go+WebSocket实现实时通信功能

    在互联网应用程序中,实时通信是一种非常重要的功能,WebSocket 是一种基于 TCP 的协议,它允许客户端和服务器之间进行双向通信,本文将介绍如何使用 Golang 创建单独的 WebSocket 会话,以实现实时通信功能,需要的朋友可以参考下
    2023-10-10
  • Go channel结构体源码和读写和关闭过程详解

    Go channel结构体源码和读写和关闭过程详解

    这篇文章主要介绍了Go channel结构体源码和读写和关闭过程,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-05-05
  • Go语言dolphinscheduler任务调度处理

    Go语言dolphinscheduler任务调度处理

    这篇文章主要为大家介绍了Go语言dolphinscheduler任务调度处理,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • Go语言Http Server框架实现一个简单的httpServer

    Go语言Http Server框架实现一个简单的httpServer

    这篇文章主要为大家介绍了Go语言Http Server框架实现一个简单的httpServer抽象,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • Go语言实现聊天小工具的示例代码

    Go语言实现聊天小工具的示例代码

    这篇文章主要为大家详细介绍了如何利用Go语言实现聊天小工具,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • gORM操作MySQL的实现

    gORM操作MySQL的实现

    本文主要介绍了gORM操作MySQL的实现,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2021-07-07
  • golang的tunny的用法示例教程

    golang的tunny的用法示例教程

    这篇文章主要为大家介绍了golang的tunny的用法示例教程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • 在golang xorm中使用postgresql的json,array类型的操作

    在golang xorm中使用postgresql的json,array类型的操作

    这篇文章主要介绍了在golang xorm中使用postgresql的json,array类型的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • 浅谈Golang是如何读取文件内容的(7种)

    浅谈Golang是如何读取文件内容的(7种)

    这篇文章主要介绍了浅谈Golang是如何读取文件内容的,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • Golang httptest包测试使用教程

    Golang httptest包测试使用教程

    这篇文章主要介绍了Golang httptest包测试使用,httptest包的理念是,非常容易模拟http服务,也就是说模拟响应写(response writer),提供给http处理器(handle),让我们测试http服务端和客户端很容易
    2023-03-03

最新评论