linux perf:如何解释和查找热点

2024-11-01 08:41:00
admin
原创
38
摘要:问题描述:我今天试用了 linux 的perf实用程序,但在解释其结果时遇到了麻烦。我习惯使用 valgrind 的 callgrind,它当然是一种与基于采样的 perf 方法完全不同的方法。我做了什么:perf record -g -p $(pidof someapp) perf report -g -n...

问题描述:

我今天试用了 linux 的perf实用程序,但在解释其结果时遇到了麻烦。我习惯使用 valgrind 的 callgrind,它当然是一种与基于采样的 perf 方法完全不同的方法。

我做了什么:

perf record -g -p $(pidof someapp)
perf report -g -n

现在我看到的是这样的:

+ 16.92% kdevelop libsqlite3.so.0.8.6 [.] 0x3fe57 ↑
+ 10.61% kdevelop libQtGui.so.4.7.3 [.] 0x81e344 ▮
+ 7.09% kdevelop libc-2.14.so [.] 0x85804 ▒
+ 4.96% kdevelop libQtGui.so.4.7.3 [.] 0x265b69 ▒
+ 3.50% kdevelop libQtCore.so.4.7.3 [.] 0x18608d ▒
+2.68%kdevelop libc-2.14.so [.] memcpy ▒
+1.15%kdevelop[kernel.kallsyms] [k]copy_user_generic_string▒
+ 0.90% kdevelop libQtGui.so.4.7.3 [.] QTransform::translate(double, double) ▒
+0.88%kdevelop libc-2.14.so [.] __libc_malloc▒
+ 0.85% kdevelop libc-2.14.so [.] memcpy
...

好吧,这些函数可能很慢,但我如何找出它们从哪里被调用?由于所有这些热点都位于外部库中,我看不到优化代码的方法。

基本上,我正在寻找某种带有累积成本注释的调用图,其中我的函数比我调用的库函数具有更高的包容性采样成本。

使用 perf 可以实现这一点吗?如果可以,怎么做?

注意:我发现“E”解开了调用图并提供了更多信息。但调用图通常不够深入和/或随机终止,没有提供有关在哪里花费了多少信息的信息。示例:

- 10.26% kate libkatepartinterfaces.so.4.6.0 [.] Kate::TextLoader::readLine(int&...
     凯特::文本加载器::readLine(int&,int&)                                            
     凯特::文本缓冲区::加载(QString const&,bool&,bool&)                              
     KateBuffer::openFile(QString const&)                                              
     KateDocument::打开文件()                                                          
     0x7fe37a81121c

这可能是我在 64 位系统上运行的问题吗?另请参阅: http: //lists.fedoraproject.org/pipermail/devel/2010-November/144952.html(我没有使用 fedora,但似乎适用于所有 64 位系统)。


解决方案 1:

在 Linux 3.7 中,perf 终于可以使用 DWARF 信息来生成调用图:

perf record --call-graph dwarf -- yourapp
perf report -g graph --no-children

很棒,但是与 VTune、KCacheGrind 或类似产品相比,curses GUI 太糟糕了...我建议尝试 FlameGraphs,它是一款非常漂亮的可视化工具:http://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html

注意:在报告步骤中,-g graph使结果输出简单易懂的“相对于总计”百分比,而不是“相对于父级”数字。--no-children将仅显示自身成本,而不是全包成本 - 我也认为这个功能非常有价值。

如果您有新的 perf 和 Intel CPU,还可以尝试 LBR 展开器,它具有更好的性能并且生成的结果文件更小:

perf record --call-graph lbr -- yourapp

这里的缺点是,与默认的 DWARF 展开器配置相比,调用堆栈深度更加有限。

解决方案 2:

您应该尝试一下热点:
https://www.kdab.com/hotspot-gui-linux-perf-profiler/

它可以在 github 上找到:https://github.com/KDAB/hotspot

例如,它能够为您生成火焰图。

火焰图

解决方案 3:

好吧,这些函数可能很慢,但我如何找出它们从哪里被调用?由于所有这些热点都位于外部库中,我看不到优化代码的方法。

你确定你的应用程序someapp是用 gcc 选项-fno-omit-frame-pointer(以及可能还有它的依赖库)构建的吗?像这样:

g++ -m64 -fno-omit-frame-pointer -g main.cpp

解决方案 4:

perf annotate你可以通过查看perf annotate 的源代码级分析来获得非常详细的源代码级报告。它看起来会像这样(厚颜无耻地从网站上偷来的):

------------------------------------------------
 Percent |   Source code & Disassembly of noploop
------------------------------------------------
         :
         :
         :
         :   Disassembly of section .text:
         :
         :   08048484 <main>:
         :   #include <string.h>
         :   #include <unistd.h>
         :   #include <sys/time.h>
         :
         :   int main(int argc, char **argv)
         :   {
    0.00 :    8048484:       55                      push   %ebp
    0.00 :    8048485:       89 e5                   mov    %esp,%ebp
[...]
    0.00 :    8048530:       eb 0b                   jmp    804853d <main+0xb9>
         :                           count++;
   14.22 :    8048532:       8b 44 24 2c             mov    0x2c(%esp),%eax
    0.00 :    8048536:       83 c0 01                add    $0x1,%eax
   14.78 :    8048539:       89 44 24 2c             mov    %eax,0x2c(%esp)
         :           memcpy(&tv_end, &tv_now, sizeof(tv_now));
         :           tv_end.tv_sec += strtol(argv[1], NULL, 10);
         :           while (tv_now.tv_sec < tv_end.tv_sec ||
         :                  tv_now.tv_usec < tv_end.tv_usec) {
         :                   count = 0;
         :                   while (count < 100000000UL)
   14.78 :    804853d:       8b 44 24 2c             mov    0x2c(%esp),%eax
   56.23 :    8048541:       3d ff e0 f5 05          cmp    $0x5f5e0ff,%eax
    0.00 :    8048546:       76 ea                   jbe    8048532 <main+0xae>
[...]

编译代码时不要忘记传递-fno-omit-frame-pointer和标志。-ggdb

解决方案 5:

除非您的程序只有很少的函数,并且几乎从不调用系统函数或 I/O,否则对程序计数器进行采样的分析器不会告诉您太多信息,正如您所发现的那样。事实上,著名的分析器gprof就是专门为解决仅针对自身时间的分析无用性而创建的(尽管它并没有成功)。

实际起作用的是对调用堆栈进行采样(从而找出调用来自何处)、按挂钟时间(从而包括 I/O 时间)并按行或按指令进行报告(从而精确定位您应该调查的函数调用,而不仅仅是它们所在的函数)。

此外,您应该寻找的统计数据是堆栈上的时间百分比,而不是调用次数,而不是平均包含函数的时间。特别是不是“自身时间”。
如果调用指令(或非调用指令)在堆栈上停留 38% 的时间,那么如果您可以摆脱它,您会节省多少?38%!
很简单,不是吗?

这种分析器的一个例子是Zoom。

关于这个问题,还有更多问题有待了解。

补充:@caf 让我搜索perf信息,由于您包含了命令行参数,-g它确实收集了堆栈样本。然后您可以获得一个调用树报告。然后,如果您确保在挂钟时间进行采样(这样您就可以获得等待时间和 CPU 时间),那么您几乎已经得到了所需的东西。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用