使用linux perf和不同的调用图模式对我的程序进行性能分析会得出不同的结果

问题描述 投票:0回答:1

我想用linux性能分析我的c ++程序。为此,我使用了以下三个命令,但我不明白为什么会得到三个完全不同的报告。

perf record --call-graph dwarf ./myProg
perf report

enter image description here

perf record --call-graph fp ./myProg
perf report

enter image description here

perf record --call-graph lbr ./myProg
perf report

enter image description here

而且我也不明白为什么main功能不是列表中最高的功能。

我的程序的逻辑如下,main函数调用getPogDocumentFromFile函数,该函数调用fromPoxml,该函数调用toPred,该函数调用applySubst,又调用subst。此外,toPredapplySubstsubst是递归函数。我希望它们会成为瓶颈。

更多评论:我的程序运行大约25分钟,它具有很高的递归性,并分配了很多(〜17Go)内存。我也用-fno-omit-frame-pointer编译并使用最新的Intel CPU。

任何想法?

编辑:

再次考虑我的问题,我意识到我不理解“儿童”专栏的含义。

到目前为止,我假设Self列是我们在调用堆栈顶部看到的具有函数的样本的百分比,Children列是具有函数在调用堆栈中的任意位置的样本的百分比。显然不是这种情况,否则main函数的子列距离100%不远。也许调用栈被截断了?还是我完全误解了探查器的工作原理?

c++ profiling perf dwarf
1个回答
0
投票

[Man page of pref report记录带有子项累积的呼叫链显示:

pref report

[我可以建议您使用 --children Accumulate callchain of children to parent entry so that then can show up in the output. The output will have a new "Children" column and will be sorted on the data. It requires callchains are recorded. See the ‘overhead calculation’ section for more details. Enabled by default, disable with --no-children. (或--no-children perf report)的perf top选项尝试非默认模式

因此,在默认模式下,当perf.data文件中有一些调用链数据时,perf报告将计算“自我”和“自我+子代”的开销并对累积的数据进行排序。这意味着,如果某个函数perf top拥有10%的“自我”样本,并调用某个叶子函数-g --no-children -p $PID_OF_PROGRAM拥有20%的“自我”样本,那么f1()自我+子代将为30%。累积的数据适用于提及当前功能的所有堆栈:用于其本身所做的工作,以及所有直接和间接子代(后代)的工作。

您可以在f2()选项中指定一些调用堆栈采样方法(dwarf / lbr / fp),它们可能有一些限制。有时方法(尤其是fp)可能无法提取部分调用堆栈。 f1()选项可能会有所帮助,但是当在可执行文件中使用它但在某些具有回调功能的库中不使用它时,则将部分提取调用堆栈。一些方法可能无法提取某些很长的调用链。否则--call-graph可能无法处理某些情况。

要检查截断的呼叫链样本,请在中间的某处使用-fno-omit-frame-pointer。在此模式下,它确实会打印所有已记录的带有所有检测到的功能名称的样本,并检查样本是否以perf reportperf script|less结尾-被截断。

否则主函数的子列将不超过100%

是,对于单线程程序以及正确记录和处理的调用堆栈,main在“子级”列中的值应为99%。对于多线程程序,第二个线程和其他线程将具有另一个根节点,如start_thread。

© www.soinside.com 2019 - 2024. All rights reserved.