Linux时间采样分析器

12

简短版:

Linux有好用的基于时间的采样分析器吗?

详细版:

通常我使用OProfile来优化我的应用程序。最近我发现了一个小问题,这让我想知道。

问题是一个紧密的循环,调用c++filt来还原C++名称。而我只是偶然发现了这段代码,当时我在追踪另一个瓶颈。OProfile并没有显示出这段代码有什么异常,所以我几乎忽略了它,但我的代码感觉告诉我要优化这个调用并查看结果。我将popen调用更改为abi::__cxa_demangle,运行时间从一分钟多减少到了一秒多。大约提高了60倍的速度。

我能否通过配置OProfile来标记popen调用呢?目前的分析数据中,OProfile认为瓶颈是堆和std::string调用(顺带一提:这些调用被优化后,运行时间减少到少于一秒,提高了2倍以上的速度)。

以下是我的OProfile配置:

$ sudo opcontrol --status
Daemon not running
Event 0: CPU_CLK_UNHALTED:90000:0:1:1
Separate options: library
vmlinux file: none
Image filter: /path/to/executable
Call-graph depth: 7
Buffer size: 65536

有没有其他适用于Linux的分析器可以找到瓶颈呢?

我怀疑问题在于OProfile仅将其样本记录到当前正在运行的进程中。我希望它始终将其样本记录到我正在分析的进程中。因此,如果该进程当前被切换出(在IO或popen调用上阻塞),OProfile将只在阻塞的调用处放置其样本。

如果我无法解决这个问题,那么OProfile仅在可执行文件接近100%的CPU使用率时才有用。它无法帮助具有低效阻塞调用的可执行文件。

5个回答

6
很高兴你问了。我认为OProfile可以做到我认为正确的事情,即在程序运行缓慢时记录堆栈样本,如果无法让您检查单个堆栈样本,则至少对于出现在样本中的每行代码进行总结,并显示该行出现在样本中的百分比。这是一个直接衡量,如果该行不存在,将节省多少的度量。这里有一次讨论。这里是另一个,还有另一个。正如保罗所说,Zoom应该可以做到。
如果您的时间从60秒变为1秒,则意味着每个堆栈样本都有59/60的概率向您显示问题。

1
Mike,你的观点非常有价值,我完全同意这种技术。你有什么想法可以通过OProfile实现基于时间的采样或者更自动化的方法,而不仅仅是在调试器中断点的方式吗? - deft_code
@Caspin:我使用的是Windows系统,不熟悉OProfile。但是这个链接(http://oprofile.sourceforge.net/doc/opreport.html)讲解了如何使用和展示堆栈采样数据。此外,这个链接(http://oprofile.sourceforge.net/doc/detailed-parameters.html#timer)讲解了定时器中断。我无法确定它是否会在I/O或其他阻塞调用期间进行采样。 - Mike Dunlavey
请注意,采样频率不需要很快,但必须能够在阻塞调用期间进行采样,除非您想对此视而不见。 - Mike Dunlavey
2
我忘了提到,lsstack 是手动获取堆栈样本的简单方法,pstack 也是如此(但没有符号)。 - Mike Dunlavey

3
尝试使用Zoom - 我相信它可以让您对所有进程进行分析 - 如果它能在这种情况下突出显示您的问题,那将是很有趣的。请点击此处了解更多信息。

Zoom版本1.6.6也没有发现问题。下一个版本的Zoom据说将拥有采样模式(“线程时间分析”),可以找到问题。 - deft_code

2

2
在尝试了这里提出的所有建议之后(除了现已停用的Zoom,它仍可从dropbox作为大文件下载),我发现没有任何东西可以做到Dunlavey先生推荐的那样。上面某些答案中列出的“快速技巧”对我来说无法构建,或者也不能为我工作。整天都在尝试各种方法……但是没有一种方法能够在一个其他简单的测试程序中找到fseek作为热点的I/O绑定。所以我又编写了另一个分析器,这次没有构建依赖关系,基于GDB,因此它应该“只需工作”适用于几乎任何可调试的代码。一个单独的CPP文件。

https://github.com/jasonrohrer/wallClockProfiler

它自动化了Dunlavey先生提出的手动过程,定期使用GDB中断目标进程并获取堆栈跟踪,然后在最后打印有关哪些堆栈跟踪最常见的报告。这些是您真正的墙钟热点。而且它确实有效。

1

看一下lsstack是如何实现的。它不需要特殊的驱动程序代码来获取当前的回溯信息。同时,将你的代码放在bitbucket或google code上。如果你完成了一个像样的项目,我会在使用时贡献错误修复。 - deft_code
@caspin,好的,现在我正在研究如何使用gdb(https://dev59.com/IVHTa4cB1Zd3GeqPQld7)来完成同样的事情。 - Vi.
我尝试了你的代码,但它挂起了,因为你正在从信号处理程序中使用fopen,这是已知会导致挂起的函数之一(你只能在信号处理程序中使用非常少量的函数)。 - Ondřej Čertík
它是否应该可靠地使用低级别的“打开/写入/关闭”而不是fopen? - Vi.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接