C语言 从 perf 获取用户空间堆栈信息



我目前正在尝试在我正在测试的PostgreSQL构建中追踪一些幻影I/O。它是一个多进程服务器,将磁盘 I/O 关联回特定的后端和查询并不简单。

我认为 Linux 的 perf 工具是理想的选择,但我正在努力捕获块 I/O 性能计数器指标并将其与用户空间活动相关联。

记录

块 I/O 请求和完成很容易,例如:

sudo perf record -g -T -u postgres -e 'block:block_rq_*'

并且记录了用户空间 PID,但没有捕获内核或用户空间堆栈,也没有能够快照用户空间进程堆的位(例如,查询文本)等。因此,当你有pid时,你不知道这个过程在做什么。只需perf script输出,如下所示:

postgres  7462 [002] 301125.113632: block:block_rq_issue: 8,0 W 0 () 208078848 + 1024 [postgres]

如果我将 -g 标志添加到perf record它将拍摄内核堆栈的快照,但不会捕获内核中捕获的性能事件的用户空间状态。用户空间堆栈仅从用户空间上升到入口点,如LWLockReleaseLWLockAcquirememcpy(mmap'd IO)、__GI___libc_write等。

那么,有什么提示吗?能够捕获用户空间堆栈的快照以响应内核事件将是理想的。

我在Fedora 19,3.11.3-201.fc19.x86_64,薛定谔的猫,perf版本为3.10.9-200.fc19.x86_64。

好的,看起来有几个部分:

  • 我在x86_64,默认情况下大多数发行版都使用 -fomit-frame-pointer 构建,如果没有帧指针,perf无法遵循堆栈;

  • ....除非它是在libunwind支持下构建的较新版本,在这种情况下,它支持 perf record -g dwarf .

看:

  • 将 libunwind 支持添加到 Perf 的补丁
  • Debian 错误725075。
  • Linux Perf:如何解释和查找热点

我在 Fedora 18 上,但同样的问题也适用。因此,如果您正在分析您正在处理的代码(就像在堆栈溢出上一样),请使用 -fno-omit-frame-pointer-ggdb 进行重建。

我开始重建perf因为我希望能够与库存 RPM 进行比较:

  • sudo yum build-dep perf
  • sudo yum install yum-utils rpmdevtools libunwind-devel
  • yumdownloader --source perf或下载相应的kernel-.....src.rpm srpm
  • rpmdev-setuptree
  • rpm -Uvh kernel-*.src.rpm
  • cd $HOME/rpmbuild/SPECS
  • rpmbuild -bp --target=$(uname -m) kernel.spec

此时,如果需要,您可以构建一个新perf

  • cd $HOME/rpmbuild/BUILD/kernel-*/linux-*/tools/perf
  • make

。我做了并测试了更新的perf如果使用 libunwind 可用构建,实际上确实捕获了一个有用的堆栈。

您还可以构建新的 rpm:

  • 编辑 kernel.spec,取消注释行%define buildid ...,将 buildid 更改为类似 .perfunwind 的内容。请注意,它%define不是% define

  • 在同一等级库中,找到:

    %global perf_make 
    make %{?_smp_mflags} -C tools/perf -s V=1 WERROR=0 NO_LIBUNWIND=1 HAVE_CPLUS_DEMANGLE=1 NO_GTK2=1 NO_LIBNUMA=1 NO_STRLCPY=1 prefix=%{_prefix}
    

    并删除NO_LIBUNWIND=1

  • rpmbuild -bb --without up --without mp --without pae --without debug --without doc --without headers --without debuginfo --without bootwrapper --without with_vdso_install --with perf kernel.spec在不构建整个内核的情况下生成新的 perf RPM。或者,如果需要,可以省略所需内核风格的--without,在这种情况下,您还需要构建标头、调试信息等。

  • sudo rpm -Uvh $HOME/rpmbuild/RPMS/x86_64/perf-*.fc19.x86_64.rpm

请参阅 Fedora 项目指南,了解如何构建自定义内核。

我已经向Fedora报告了这个问题;他们不应该使用NO_LIBUNWIND=1。请参阅错误1025603。

一旦你有一个重建的perf你可以使用perf record -g dwarf来获得完整的堆栈。

最新更新