linux 的 perf 实用程序如何理解堆栈跟踪?

     2023-03-06     232

关键词:

【中文标题】linux 的 perf 实用程序如何理解堆栈跟踪?【英文标题】:How does linux's perf utility understand stack traces? 【发布时间】:2016-07-09 01:43:42 【问题描述】:

Linux 的 perf 实用程序被 Brendan Gregg 用于为 c/c++、jvm 代码、nodejs 代码等生成火焰图。

Linux 内核本身是否理解堆栈跟踪?即使进程是用完全不同的语言编写的,我在哪里可以了解有关工具如何自省进程堆栈跟踪的更多信息?

【问题讨论】:

嗯,这与编写进程源代码的语言无关,而与运行的二进制文件有关。最终,语言代码被转换为在处理器上运行的二进制(可执行文件)。 linux 的可执行文件可能是ELF 格式。堆栈跟踪是为此 - 二进制 - 代码生成的。如果二进制文件有描述其过程的符号表——你将在跟踪中有一些正常的名称。 (Brendan Gregg 描述了 Java 缺少符号的问题,火焰图上对应的空白部分。) @xealits 你有指向 Brendan 关于 java 缺失符号的注释的链接吗?这可能会为我填补缺失的部分。 xealits,ELF 没有堆栈跟踪;有时 linux 内核很难找到完整的调用堆栈 - 编译器优化可能会省略一些帧指针。一些 Java VM 具有堆栈帧格式的魔力:brendangregg.com/perf.html“4.4 堆栈跟踪。始终使用帧指针进行编译。省略帧指针是一种破坏调试器的恶意编译器优化,.. 从 3.9 内核开始,perf_events 支持一种解决方法用户级堆栈中缺少帧指针:libunwind,它使用 dwarf。...由于 x86 上的热点,Java 可能无法显示完整的堆栈.. "完全不同的语言?" - 哪些语言?你的 CPU 架构是什么? 一些链接:"Java in flames","JIT symbols"——所以对于 Linux Java 是虚拟处理器(Java Virtual Machine,JVM),Java 程序在 JVM 中运行,它们不是 Linux 进程,而是不被视为原生。他以某种方式为 Linux 增加了 JVM 内部的可见性,并且用户的 Java 程序,他们的堆栈,变得可见。 @osgx 我对 ELF 和所有这些问题都不是很精通,因此我离题了。 【参考方案1】:

Gregg 在perf 中有关于堆栈跟踪的简短介绍: http://www.brendangregg.com/perf.html

4.4 堆栈跟踪

始终使用帧指针进行编译。省略帧指针是一种邪恶的编译器优化,它会破坏调试器,可悲的是,它通常是默认设置。没有它们,您可能会看到 perf_events 中的不完整堆栈...有两种方法可以解决此问题:使用 dwarf 数据展开堆栈,或返回帧指针。

矮人

从 3.9 内核开始,perf_events 支持一种解决用户级堆栈中缺少帧指针的方法:libunwind,它使用 dwarf。这可以使用“-g dwarf”来启用。 ... 编译器优化 (-O2),在这种情况下省略了帧指针。 ... 重新编译 .. 使用 -fno-omit-frame-pointer:

非 C 风格的语言可能有不同的帧格式,或者也可能省略帧指针:

4.3。 JIT 符号(Java、Node.js)

具有虚拟机 (VM) 的程序,如 Java 的 JVM 和 node 的 v8,执行自己的虚拟处理器,它有自己的执行功能和管理堆栈的方式。如果你使用 perf_events 分析这些,你会看到 VM 引擎的符号。perf_events 支持 JIT 来解决这个问题,这需要 VM 维护一个 /tmp/perf-PID.map 文件以进行符号转换。

请注意,由于 x86 上的热点忽略了帧指针(就像 gcc 一样),Java 可能不会显示完整的堆栈。在较新的版本(JDK 8u60+)上,您可以使用-XX:+PreserveFramePointer 选项来修复此行为,...

Gregg 关于 Java 和堆栈跟踪的博客文章: http://techblog.netflix.com/2015/07/java-in-flames.html ("Fixing Frame Pointers" - 在某些 JDK8 版本和 JDK9 中通过在程序启动时添加选项来修复)

现在,你的问题:

linux 的 perf 实用程序如何理解堆栈跟踪?

perf utility 基本上(在早期版本中)只是解析从 linux 内核子系统“perf_events”(有时是“events”)返回的数据,通过系统调用 perf_event_open 访问。对于调用堆栈跟踪,有PERF_SAMPLE_CALLCHAIN / PERF_SAMPLE_STACK_USER 选项:

sample_type PERF_SAMPLE_CALLCHAIN 记录调用链(堆栈回溯)。

          PERF_SAMPLE_STACK_USER (since Linux 3.7)
                 Records the user level stack, allowing stack unwinding.

Linux 内核本身是否理解堆栈跟踪?

它可能理解(如果实施)也可能不理解,具体取决于您的 CPU 架构。采样(从实时进程获取/读取调用堆栈)调用链的功能在内核的体系结构独立部分中定义为__weak,主体为空:

http://lxr.free-electrons.com/source/kernel/events/callchain.c?v=4.4#L26

 27 __weak void perf_callchain_kernel(struct perf_callchain_entry *entry,
 28                                   struct pt_regs *regs)
 29 
 30 
 31 
 32 __weak void perf_callchain_user(struct perf_callchain_entry *entry,
 33                                 struct pt_regs *regs)
 34 
 35 

在 4.4 内核中,用户空间调用链采样器在 x86/x86_64、ARC、SPARC、ARM/ARM64、Xtensa、Tilera TILE、PowerPC、Imagination Meta 的内核架构相关部分重新定义:

http://lxr.free-electrons.com/ident?v=4.4;i=perf_callchain_user

arch/x86/kernel/cpu/perf_event.c, line 2279
arch/arc/kernel/perf_event.c, line 72
arch/sparc/kernel/perf_event.c, line 1829
arch/arm/kernel/perf_callchain.c, line 62
arch/xtensa/kernel/perf_event.c, line 339
arch/tile/kernel/perf_event.c, line 995
arch/arm64/kernel/perf_callchain.c, line 109
arch/powerpc/perf/callchain.c, line 490
arch/metag/kernel/perf_callchain.c, line 59

对于某些架构和/或某些模式,从用户堆栈读取调用链可能并非易事。

您使用什么 CPU 架构?使用什么语言和虚拟机?

我可以在哪里阅读更多关于工具如何自省进程堆栈跟踪的信息,即使进程是用完全不同的语言编写的?

您可以尝试gdb 和/或该语言的调试器或libc 的backtrace function 或在libunwind 中支持只读展开(有local backtrace example in libunwind、show_backtrace())。

他们可能更好地支持帧解析/与语言的虚拟机或展开信息更好地集成。如果 gdb(使用 backtrace 命令)或其他调试器无法从正在运行的程序中获取堆栈跟踪,则可能根本无法获取堆栈跟踪。

如果他们可以得到调用跟踪,但 perf 不能(即使在使用 -fno-omit-frame-pointer 重新编译 C/C++ 之后),可以将这种架构 + 帧格式组合的支持添加到 perf_eventsperf

有几个博客提供了一些关于一般回溯问题和解决方案的信息:

http://eli.thegreenplace.net/2015/programmatic-access-to-the-call-stack-in-c/ - 使用 libunwind 进行本地回溯 http://codingrelic.geekhold.com/2009/05/pre-mortem-backtracing.html gcc 的 __builtin_return_address(N) vs glibc 的 backtrace() vs libunwind 的本地回溯 http://lucumr.pocoo.org/2014/10/30/dont-panic/ 生锈的回溯和展开 https://github.com/gperftools/gperftools/wiki/gperftools'-stacktrace-capturing-methods-and-their-issues 与 gperftools 基于软件计时器的分析器库中的回溯相同的问题

perf_events/perf的矮人支持:

https://lwn.net/Articles/499116/ [RFCv4 00/16] perf:添加回溯后 dwarf 展开,2012 年 5 月 https://lwn.net/Articles/507753/ [PATCHv7 00/17] 性能:在 dwarf 展开后添加回溯,2012 年 7 月 https://wiki.linaro.org/LEG/Engineering/TOOLS/perf-callstack-unwinding - Dwarf 在 ARM 7/8 上展开以获得性能 https://wiki.linaro.org/KenWerner/Sandbox/libunwind#libunwind_ARM_unwind_methods - 也有非矮人方法

【讨论】:

以及有关 perf 如何对分析中断进行编程的信息:***.com/questions/28661430/… 默认情况下,基于 Dwarf 的堆栈跟踪受到限制,perf record--call-graph dwarf,81920 选项具有更大的值可能有助于获得更详细的调用堆栈。

perf 如何采样内核堆栈?

...不同进程/线程的堆栈的内核部分。目的是编写一个应用程序,可以对其他进程/线程的调用堆栈进行采样,即使它们当前位于内核中。问候【问题讨论】 查看详情

如何使用 linux perf 工具进行代码理解

】如何使用linuxperf工具进行代码理解【英文标题】:Howtouselinuxperftoolforcodecomprehension【发布时间】:2015-08-0716:50:17【问题描述】:我对“perf”记录调用图的能力着迷,并试图了解如何使用它来理解新的代码库。我在调试模式下编... 查看详情

如何阅读和理解 java 堆栈跟踪? [复制]

】如何阅读和理解java堆栈跟踪?[复制]【英文标题】:Howtoreadandunderstandthejavastacktrace?[duplicate]【发布时间】:2012-09-2304:12:35【问题描述】:例如,我得到了这样的堆栈跟踪:java.lang.NullPointerExceptionabc.investxa.presentation.controllers.Unix... 查看详情

从堆栈跟踪中获取更多详细信息

...有关Python异常的更详细的堆栈跟踪?我希望找到一个包装实用程序/模块或其他方式来从堆栈跟踪中获取更多信息,而无需实际修改生成它的Python脚本。我希望能够在运行单元测试、文档测试或从shell运行实用程序或内联脚本时使... 查看详情

如何正确读取/解释原始 C# 堆栈跟踪?

...】:2017-08-1810:52:41【问题描述】:我正在阅读来自UWP应用程序(C#,使用.NETNative编译)的一些崩溃报告,我很难理解堆栈跟踪中使用的确切语法/格式。我尝试在互联网上寻找一些指南,但没有找到任何有用的东西。这里有几个... 查看详情

在 C# 中如何收集程序崩溃的堆栈跟踪

】在C#中如何收集程序崩溃的堆栈跟踪【英文标题】:InC#howtocollectstacktraceofprogramcrash【发布时间】:2012-04-2911:40:42【问题描述】:我是C#新手。我正在编写一个基于桌面表单的小型应用程序,我需要在应用程序中具有此功能。如... 查看详情

应用程序能否以编程方式生成自己的堆栈跟踪?

】应用程序能否以编程方式生成自己的堆栈跟踪?【英文标题】:Cananapplicationprogrammaticallygenerateitsownstacktrace?【发布时间】:2011-12-2307:44:52【问题描述】:我有一个用C语言编写的程序,可以在Linux、MacOS和Windows上运行。有没有办... 查看详情

tomcat:如何打开 jdbc:oracle 连接的堆栈跟踪?

...ce?【发布时间】:2013-01-1610:31:57【问题描述】:让Web应用程序跨多个位置运行,通过在linux上运行这个命令,我可以看到很多连接堆积:ps-ef|grepLOCAL向我显示带有进程ID的活动oracle连接数,连接数每小时增加5-7个 查看详情

Maven:如何防止 exec 插件显示其堆栈跟踪?

】Maven:如何防止exec插件显示其堆栈跟踪?【英文标题】:Maven:howtopreventexecplugintodisplayitsstacktrace?【发布时间】:2019-05-0607:50:19【问题描述】:下面的简单mavenexec插件显示了一个堆栈跟踪,这让我的用户很难理解正在发生的事情... 查看详情

在linux平台上用c/c++打印进程的所有线程堆栈跟踪

...e()api,但问题是它只提供当前线程的堆栈跟踪。有谁知道如何将它与每个正在 查看详情

如何阅读这个 iOS 堆栈跟踪?

...面我没有那么经验。我正在使用ReactNative构建一个iOS应用程序,我的应用程序有时会意外崩溃。阅读崩溃日志,这是我得到的:IncidentIdentifier:B03D5F95-EF 查看详情

从 perf 获取用户空间堆栈信息

】从perf获取用户空间堆栈信息【英文标题】:Gettinguser-spacestackinformationfromperf【发布时间】:2013-11-0102:30:44【问题描述】:我目前正在尝试在我正在测试的PostgreSQL构建中追踪一些幻像I/O。它是一个多进程服务器,将磁盘I/O关联... 查看详情

perf--linux下的系统性能调优工具

...rf简介Perf是用来进行软件性能分析的工具。通过它,应用程序可以利用PMU,tracepoint和内核中的特殊计数器来进行性能统计。它不但可以分析指定应用程序的性能问题(perthread),也可以用来分析内核的性能问题,当然也可以同时分... 查看详情

您如何在 Heroku 上运行实用程序服务?

】您如何在Heroku上运行实用程序服务?【英文标题】:HowdoyourunutilityservicesonHeroku?【发布时间】:2012-06-1715:35:19【问题描述】:Heroku非常适合制作创意原型和运行简单的Web服务,我经常使用它来运行Flask和Django等PythonWeb服务并尝... 查看详情

perf--linux下的系统性能调优工具

...rf简介Perf是用来进行软件性能分析的工具。通过它,应用程序可以利用PMU,tracepoint和内核中的特殊计数器来进行性能统计。它不但可以分析指定应用程序的性能问题(perthread),也可以用来分析内核的性能问题,当然也可以同时分... 查看详情

perf--linux下的系统性能调优工具,第1部分

...rf简介Perf是用来进行软件性能分析的工具。通过它,应用程序可以利用PMU,tracepoint和内核中的特殊计数器来进行性能统计。它不但可以分析指定应用程序的性能问题(perthread),也可以用来分析内核的性能问题,当然也可以同时分... 查看详情

perf性能分析工具(代码片段)

...功能和软件(软件计数器、tracepoint)功能。通过perf,应用程序可以利用PMU、tracepoint和内核中的计数器来进行性能统计。它不但可以分析制定应用程序的性能问题(perthread),也可以用来分析内核的性能问题,当然也可以同事分析... 查看详情

使用 rxjs 时如何获取错误的堆栈跟踪?

...描述】:我正在使用angular-cli构建一个小型angular2Web应用程序,并且正在使用chromedev-tools进行调试。如果我每次都需要猜测错误的来源以及该错误的堆栈跟踪是什么,那么显然我做错了。以这个错误为例:error_h 查看详情