从 perf 获取用户空间堆栈信息
Posted
技术标签:
【中文标题】从 perf 获取用户空间堆栈信息【英文标题】:Getting user-space stack information from perf 【发布时间】:2013-11-01 02:30:44 【问题描述】:我目前正在尝试在我正在测试的 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
,它将拍摄内核 堆栈的快照,但不会捕获内核中捕获的性能事件的用户空间状态。用户空间堆栈仅从用户空间上升到入口点,如LWLockRelease
、LWLockAcquire
、memcpy
(mmap'd IO)、__GI___libc_write
等。
所以。有小费吗?能够捕获 user-space 堆栈的快照以响应 kernel 事件将是理想的选择。
我使用的是 Fedora 19,3.11.3-201.fc19.x86_64,薛定谔的猫,性能版本为 3.10.9-200.fc19.x86_64。
【问题讨论】:
回到这一点,另一种可能性可能是使用 frace / systemtap / uprobes / ... 代替。在 linux.conf.au 2014 上的一次演讲表明,此时 systemtap 可能更容易做到这一点。 【参考方案1】:好的,看起来有几个部分:
我在 x86_64 上,大多数发行版默认使用 -fomit-frame-pointer
构建,而 perf
在没有帧指针的情况下无法跟随堆栈;
.... 除非它是支持libunwind
构建的较新版本,在这种情况下它支持perf record -g dwarf
。
见:
the patch adding libunwind support to Perf Debian bug 725075。 linux perf: how to interpret and find hotspots我在 Fedora 18 上,但 the same issue applies。因此,如果您正在分析您正在处理的代码(可能在 Stack Overflow 上),请使用 -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
。
在同一个spec文件中,找到:
%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
见the fedora project guide on building a custom kernel。
我已经向 Fedora 报告了这个问题;他们不应该使用NO_LIBUNWIND=1
。见bug 1025603。
一旦你重建了perf
,你就可以使用perf record -g dwarf
来获得完整的堆栈。
【讨论】:
@ErwinBrandstetter 您可能会喜欢后续博客文章:blog.2ndquadrant.com/tracing-postgresql-perf以上是关于从 perf 获取用户空间堆栈信息的主要内容,如果未能解决你的问题,请参考以下文章