关键词:
【中文标题】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_events
和perf
。
有几个博客提供了一些关于一般回溯问题和解决方案的信息:
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
的矮人支持:
【讨论】:
以及有关 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 查看详情