在我看到CppCon 2015的这个演讲之后,我想对一些程序进行概述.我下载了那个人在谈话中使用的相同Google基准库,用适当的开关编译我的程序,将其链接到它,然后使用perf记录一次跑步.报告选项给了我这个:
正如您所看到的,函数名称不是很易读.我认为这与C++名称修改有关.有趣的是,所有的功能名称都在视频中正确显示给那个发表演讲的人,但不适合我.我不认为这是完全缺少符号信息的情况,因为在这种情况下我只会看到内存地址.由于某种原因,perf不能"撤消"我的C++名称,这看起来很令人沮丧.
我正在使用gcc(g ++)版本5.2.1,perf是版本4.2.6,我在编译时使用这些开关:
-I
我不使用的原因-fno-omit-frame-pointer
是我使用了-gdwarf-2
选项,它将调试信息留在矮人可执行文件中,这是在这种情况下保留帧指针的替代方法.这也意味着我--call-graph "dwarf"
转到了perf record
.无论如何,我也尝试了帧指针方法,它给出了相同的结果,所以这并不重要.
那么为什么在这种情况下不会"撤消"C++名称错误?这与使用GCC有什么关系,这当然意味着我正在使用libstdc ++?
当perf report
给你错位的名称一样_Z*
,_ZN*
,_ZL*
等,这意味着你的perf
工具是没有获得编译demangling功能或禁用它.有一些代码可以在Makefile中检测demangler:
http://elixir.free-electrons.com/linux/v4.2.6/source/tools/perf/Makefile.perf
# Define NO_DEMANGLE if you do not want C++ symbol demangling. # Define NO_LIBELF if you do not want libelf dependency (e.g. cross-builds)
http://elixir.free-electrons.com/linux/v4.2.6/source/tools/perf/config/Makefile
ifdef NO_LIBELF ... NO_DEMANGLE := 1 ... else ifeq ($(feature-libelf), 0) ifeq ($(feature-glibc), 1) LIBC_SUPPORT := 1 endif ... ifeq ($(LIBC_SUPPORT),1) ... NO_DEMANGLE := 1 ...
测试在tools/build/feature
目录中:http://elixir.free-electrons.com/linux/v4.2.6/source/tools/build/feature并且如果使用elf_begin
libelf函数的测试程序启用了libelf功能(
elfutils包的头,-lelf
链接)是否可用(并返回一些内容?是否有运行测试?当内核构建器机器无法直接运行目标机器elf二进制文件./test-libelf.bin
并且必须使用ssh到真机或某些用户/系统qemu 时,交叉构建怎么办?).
执行demangling的perf实现中的代码(使用cplus_demangle
if HAVE_CPLUS_DEMANGLE_SUPPORT定义,使用no demangle是在Makefile之后设置的NO_DEMANGLE,使用bfd.h和bfd_demangle
函数docs - 2.3.1.24 bfd_demangle):http:
//elixir.free-electrons.com /linux/v4.2.6/source/tools/perf/util/symbol-elf.c#L19
#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT extern char *cplus_demangle(const char *, int); static inline char *bfd_demangle(void __maybe_unused *v, const char *c, int i) { return cplus_demangle(c, i); } #else #ifdef NO_DEMANGLE static inline char *bfd_demangle(void __maybe_unused *v, const char __maybe_unused *c, int __maybe_unused i) { return NULL; } #else #define PACKAGE 'perf' #include#endif
这一切都有点奇怪(在C++ 11时代后期的Linux世界中仍然没有标准的c ++ demangle函数?).并且你的性能被错误编译或配置错误 - 这就是为什么它不能解析名称的原因.billyw 联系了Michal Fapso的回答说这是ubuntu的错误1396654 - https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1396654.
您可能会破坏使用c++filt
程序过滤perf的输出,但它会阻止您使用perf的交互式默认TUI接口(添加less
或写入文本文件以查看具有正常pageDown/pageUp的非常长的列表):
perf report | c++filt | less perf annotate function_name | c++filt | less # or: perf annotate -s function_name | c++filt | less
或者您可以按照billyw在评论中的建议更新/重新编译您的性能
4 ^看来你在Ubuntu上.我怀疑这是你的问题和解决方案:https://stackoverflow.com/a/34061874/2166274 - billyw 2016年3月3日17:31