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配置存放文件路径
相关推荐
2401_857622666 小时前
SpringBoot框架下校园资料库的构建与优化
spring boot·后端·php
2402_857589367 小时前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
哎呦没8 小时前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
_.Switch8 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
韩楚风9 小时前
【linux 多进程并发】linux进程状态与生命周期各阶段转换,进程状态查看分析,助力高性能优化
linux·服务器·性能优化·架构·gnu
杨哥带你写代码10 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
AskHarries10 小时前
读《show your work》的一点感悟
后端
A尘埃10 小时前
SpringBoot的数据访问
java·spring boot·后端
yang-230710 小时前
端口冲突的解决方案以及SpringBoot自动检测可用端口demo
java·spring boot·后端
Marst Code10 小时前
(Django)初步使用
后端·python·django