在我看到来自CppCon 2015的this讲话之后,我想对一些程序进行概述。我下载了该人在谈话中使用的相同Google基准库,用适当的开关编译了我的程序,将它链接到它,然后使用perf来记录运行。报告选项给了我这个:
正如您所看到的,函数名称不是很易读。我认为这与C ++名称修改有关。有趣的是,所有的功能名称都在视频中正确显示给那个发表演讲的人,但不适合我。我不认为这是一个完全错过符号信息的情况,因为在那种情况下我只会看到内存地址。出于某种原因,perf不能"撤消" C ++名称对我来说很糟糕,这看起来很令人沮丧。
我使用gcc(g ++)版本5.2.1,perf是版本4.2.6,我在编译时使用这些开关:
-I<my own include path> -L<path to the benchmark library> -O3 -std=c++14 -gdwarf-2 -fno-rtti -Wall -pedantic -lbenchmark -pthread
我不使用-fno-omit-frame-pointer
的原因是我使用-gdwarf-2
选项,这会在矮人可执行文件中留下调试信息,这是将帧指针保留在在这种情况下。这也意味着我将--call-graph "dwarf"
传递给perf record
。无论如何,我也尝试了帧指针方法,它给出了相同的结果,所以这并不重要。
那么为什么没有&#34;撤消&#34;在这种情况下,C ++名称是否会崩溃?这与使用GCC有什么关系,这当然意味着我使用libstdc ++?
答案 0 :(得分:7)
当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如果测试程序使用libelf的elf_begin
函数(<libelf.h>
header of elfutils package,-lelf
链接),则启用了libelf功能可用(并返回一些东西?是否有运行测试?当内核构建器机器无法直接使用./test-libelf.bin
运行目标机器精灵二进制文件时必须使用ssh到真实机器或某些用户/系统qemu? )。
执行demangling的perf实现中的代码(如果定义了HAVE_CPLUS_DEMANGLE_SUPPORT则使用cplus_demangle
,使用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 <bfd.h>
#endif
这一切都有点奇怪(在C ++ 11时代后期的Linux世界中仍然没有标准的c ++ demangle函数?)。并且你的性能被错误编译或配置错误 - 这就是为什么它不能解析名称的原因。 billyw linked answer 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
中his comment的建议更新/重新编译您的性能4 ^看来你在Ubuntu上。我怀疑这是你的问题和解决方案:https://stackoverflow.com/a/34061874/2166274 - billyw 2016年3月3日17:31