perf record竟会导致磁盘满载?

背景

在某服务的测试环境中,/root目录挂载的是一块20G的磁盘。每个节点可能会运行多个实例,我们会在环境上进行性能测试、性能分析等操作。在某次测试的过程中,我们发现系统盘的20G已被占满。

由于一般的环境都是这样处理的,所以这里我们不考虑重新划盘这样的解决方案。

问题发现与分析

是什么占据了磁盘?

我们查看每个文件夹的大小:

shell 复制代码
du -h --max-depth=1

发现在20G的空间中,除了一些必要的文件外,有大约8G.debug文件夹占据,此外还有2Gperf采集到的数据。perf采集到的数据直接删除即可,我们重点关注.debug文件夹。.debug文件夹是用来保存可执行文件对应的debug信息的。

进入.debug文件夹下,我们发现了和可执行文件的路径几乎一致的路径。例如可执行文件testcpp路径为/root/workplace/test/testcpp,对应在.debug下的路径就是/root/.debug/root/workplace/test/testcpp/1ec9a7a87620face349c8f562de67d00e7a1cfa2,这里的1ec9a7a87620face349c8f562de67d00e7a1cfa2是这个可执行文件的buildid。这里buldid是这个可执行文件在编译的时候生成的。我们可以用file来进行查看:

由于测试环境上会运行多个实例,所以在.debug文件夹下会出现多个实例的elf文件,这就导致整体的存储占用比较高。

是什么产生了这些文件?

从过去使用perf的经验中,笔者了解到perf script可能会使用到.debug文件夹下的内容,同时perf也有perf buildid-list这样明显和.debug文件相关联的部分,因此笔者首先将目光放到了perf上。

显然这是一个已经执行过perf的环境,所以我们不妨找一个没有.debug文件夹的环境,执行perf试试:

可以看到在这里生成了.debug目录。

我们通过strace抓取perf record执行的情况:

shell 复制代码
strace -o strace perf record -ag -F 999 -- sleep 2

在输出的strace结果中直接搜索.debug

可以看到perf直接去创建了.debug目录并且会去检查其子目录的情况,并进行子目录的创建,也即perf record会生成.debug文件夹及对应的文件

perf config注释中,我们也找到了相关说明:

The recording tools also stores a hard link or copy in a per-user directory, $HOME/.debug/, of binaries, shared libraries, /proc/kallsyms and /proc/kcore files to be used at analysis time.

问题解决

在前面我们提到,我们不考虑增加存储这样的解法,因此我们考虑如下的两个思路:

  • 不生成.debug
  • .debug生成到其他目录下

不生成.debug

如何不生成.debug目录

我们首先去查阅了perf record的文档,在文档中我们发现可以用-B/-N选项关闭:

-B, --no-buildid Do not save the build ids of binaries in the perf.data files. This skips post processing after recording, which sometimes makes the final step in the recording process to take a long time, as it needs to process all events looking for mmap records. The downside is that it can misresolve symbols if the workload binaries used when recording get locally rebuilt or upgraded, because the only key available in this case is the pathname. You can also set the "record.build-id" config variable to 'skip to have this behaviour permanently.

-N, --no-buildid-cache Do not update the buildid cache. This saves some overhead in situations where the information in the perf.data file (which includes buildids) is sufficient. You can also set the "record.build-id" config variable to no-cache to have the same effect.

我们实际验证一下:

不生成的影响

根据注释来说,我们会发现-B-N的作用并不是完全一致的,前者是不保存相关的二进制信息,而后者是不做更新。这会有什么后果呢?

perf的使用流程中,我们往往会使用perf script去解析perf record生成的数据,在解析的过程中,会涉及到地址与函数的转换,这里就需要我们的debug信息的参与。在实际的转换过程中,perf script会通过以下的渠道去找对应的二进制文件:

  • 可执行文件目录,例如前文提到的/root/workplace/test/testcpp;如果是容器环境,会首先进行setns操作;
  • $HOME/.debug目录下的文件(默认情况下);
  • /usr/lib/debug目录下的文件;

perf会进行如下的操作:

Each executable and shared library in modern distributions comes with a content based identifier that, if available, will be inserted in a perf.data file header to, at analysis time find what is needed to do symbol resolution, code annotation, etc.

因此,正如注释中说到的,如果可执行文件目录的文件发生了变更,就会导致错误的匹配。这也就是.debug保存的原因,让perf能够在即使可执行文件消失的情况下也可以正确的解析。所以如果环境上的程序不会发生太多变化的话,不保存相关信息也是可以的。

将.debug生成到其他目录下

在前面提到的注释中,我们发现也可以通过进行配置的方式来调整perf record执行的情况,我们查看perf config的选项,发现如下的选项:

buildid\] # Default, disable using /dev/null dir = \~/.debug

因此我们可以将该目录生成到其他路径中,不使用该系统盘路径即可。下面是使用perf config切换路径的例子:

小结

本文基于在实际情况中遇到的磁盘满载问题,进行了一系列的探索,结论如下:

  • 为了更好的做解析,perf record默认会将诸多debug文件放到~/.debug文件夹下;
  • 可以通过-B/-N选项禁止该行为
  • 可以通过perf config配置存放文件路径
相关推荐
小图图13 小时前
Claude Code 黑箱揭秘
前端·后端
bobz96513 小时前
新研究:纯强化学习可激发大模型高级推理能力
后端
shark_chili13 小时前
解密计算机心脏:CPU南北桥技术发展全解析
后端
努力的小雨13 小时前
混元开源之力:spring-ai-hunyuan 项目功能升级与实战体验
后端·github
bobz96513 小时前
calico vs cilium
后端
绝无仅有14 小时前
面试实战总结:数据结构与算法面试常见问题解析
后端·面试·github
绝无仅有14 小时前
Docker 面试常见问题及解答
后端·面试·github
程序员爱钓鱼14 小时前
Go语言100个实战案例-项目实战篇:股票行情数据爬虫
后端·go·trae
IT_陈寒14 小时前
Redis 性能翻倍的 7 个冷门技巧,第 5 个大多数人都不知道!
前端·人工智能·后端
你的人类朋友1 天前
说说签名与验签
后端