超越堆栈采样:C++性能分析工具

154

一个骇客的故事

日期是12/02/10。离圣诞节还有几天,我作为一名 windows 程序员已经遭遇了严重的障碍。我尝试使用 AQTime、Sleepy、Shiny 和 Very Sleepy,而 VTune 正在安装中。我尝试使用 VS2008 分析器,但它往往无法理解并且非常困难。我使用了随机暂停技术,检查了调用树和函数跟踪。但令人难受和痛苦的事实是,我正在处理的应用程序包含超过一百万行代码,可能还有另外一百万行的第三方应用程序。

我需要更好的工具。我阅读了其他话题。 我尝试了每个话题中列出的每个分析器。必须有比这些低劣而昂贵的选项或为几乎没有收益而做出的荒谬数量的工作更好的东西。更进一步使问题复杂化的是,我们的代码有很多线程,并运行许多 Qt 事件循环,其中一些由于时间延迟而在重载时崩溃。不要问我为什么我们要运行多个事件循环,没有人可以告诉我。

在 Windows 环境中有类似 Valgrind 的选项吗?
有比我已经尝试过的一大堆破碎工具更好的东西吗?
有没有旨在与 Qt 集成并具有事件队列有用显示的工具?

以下是我尝试的所有工具列表,其中真正有用的工具用斜体表示:

  • AQTime: 相当不错!在深度递归时会有些麻烦,但对于这些情况,调用图是正确的,并且可以用来澄清任何可能存在的困惑。虽然不是完美的工具,但值得一试。它可能适合您的需求,并且大部分时间对我来说足够好。
  • 调试模式下的随机暂停攻击: 很多时候信息不足。一个好的工具,但不是完整的解决方案。
  • Parallel Studios: 核心选项。比较突兀、奇怪,但功能强大。 我认为您应该使用30天的评估版,并确定它是否适合您的需求。 它确实很酷。
  • AMD Codeanalyst: 非常棒,易于使用,但非常容易崩溃,但我认为这是环境问题。 我建议尝试一下,因为它是免费的。
  • Luke Stackwalker: 在小型项目上运行良好,我们的项目运行良好有点费劲。 一些好的结果,对于我的个人任务,它绝对可以取代Sleepy。
  • PurifyPlus: 不支持Win-x64环境,尤其是Windows 7。否则非常出色。 我在其他部门的一些同事中有很多人都很喜欢它。
  • VS2008 Profiler: 在函数跟踪模式下以所需的分辨率产生超过100GB的输出。好的方面是可以产生可靠的结果。
  • GProf: 需要GCC才能达到中等效果。
  • VTune: VTune的W7支持边缘犯罪。否则非常出色。
  • PIN: 我需要自己编写工具,因此这是一种最后的选择。
  • Sleepy\VerySleepy: 对于较小的应用程序有用,但在这里无法帮助我。
  • EasyProfiler: 如果您不介意手动注入代码以指示在哪里进行插装,则还不错。
  • Valgrind:仅限*nix环境,但在该环境下非常出色。
  • OProfile:仅限Linux。
  • Proffy:他们枪杀了野马。

建议的工具我没有尝试过:

  • XPerf:
  • Glowcode:
  • Devpartner:

注:目前使用Intel环境、VS2008、boost库以及Qt 4+,还有一个让人头疼的问题:通过Trolltech实现的Qt/MFC集成。


现在:将近两周过去了,看起来我的问题已经解决了。感谢各种工具(包括列表中的几乎所有工具和我个人的一些技巧),我们找到了主要的瓶颈。然而,我仍将继续测试、探索和尝试新的分析器以及新的技术。为什么?因为我要向你们证明自己能行,而你们很棒。这可能会稍微延长时间表,但我仍然非常兴奋地尝试新工具。

简介
除了许多其他问题外,最近一些组件被切换到了错误的线程模型,导致由于底层代码突然不再是多线程的,出现了严重的停顿问题。我不能透露更多信息,因为这违反了我的保密协议,但我可以告诉你,即使是普通的检查或正常的代码审核也永远不会发现这个问题。没有分析器、调用图和随机暂停结合起来使用,我们仍然会对美丽的蓝色天空弥漫着怒火。幸运的是,我与一些我曾经遇到过的最好的黑客共事,并且我可以访问一个充满了优秀工具和优秀人才的“宇宙世界”。

各位,我非常感激你们,遗憾的是我没有足够的声誉去奖励每个人。我仍然认为这是一个比SO上现有答案更好的问题。因此,在接下来的三个星期里,我将提供我能够提供的最大赏金,并授予一个我认为不常见的最好的工具的答案。三周后,我们希望积累一个分析器的最终概况。

精华版
使用性能分析工具。即使是 Ritchie、Kernighan、Bentley 和 Knuth 也在使用它们。不管你认为自己有多强,都请使用性能分析工具。如果你目前的工具不能达到预期效果,就寻找其他工具。如果找不到合适的工具,就自己开发一个。如果自己无法开发或者只遇到小的问题,或者卡住了,可以使用随机暂停技术。如果所有的方法都失败了,可以雇用一些研究生来开发性能分析工具。


长远视角版
因此,我想写一篇回顾文章。我选择与 Parallel Studios 大量合作,部分原因是它实际上是建立在 PIN 工具之上的。由于曾经与一些涉及研究人员进行过学术交往,所以我认为这可能是一种质量标志。幸运的是,我是正确的。虽然 GUI 有点糟糕,但我发现 IPS 非常有用,尽管我不能轻易地为每个人推荐它。关键是,在许多其他性能分析工具(如 AQT)中,没有明显的方法来获取代码行级别的命中次数,这是我用于检查分支选择率等问题非常有用的东西。总体而言,我也喜欢使用 AQTime,并且我发现他们的支持非常响应。同样需要澄清的是:他们的许多功能都不起作用,其中一些在 Win7x64 上甚至会导致崩溃。XPerf 的性能表现也很出色,但对于需要进行详细采样的某些应用程序来说,速度非常慢。

目前,我必须说,我认为在 W7x64 环境中,没有一个明确的选项可以对 C++ 代码进行性能分析,但肯定存在一些根本不提供任何有用服务的选项。


18
你考虑过换一份工作吗? :) - Nikolai Fetissov
10
除了这里,我还能在哪里解决这么难的谜题?我想我可以回去搞内核开发,但那的报酬不如这个。 - Jake Kurzer
3
@Kos 我认为,要让gprof有用,你必须使用gcc工具集并编译-pg,否则它不会生成gprof.out文件。在OP的情况下,他似乎正在使用msvc,这排除了使用gprof的可能性。再说了,如果列表中的其他工具不能满足他的需求,我也不认为gprof会更好。 - greatwolf
2
@Marc Gravell,我想这很公平。对我来说,这似乎是一个奇怪的启发式方法,即最好维护的帖子突然进入社区领域,实际上产生了这样一种情况:你更新和维护问题或答案的次数越多,你在整个社区中得到的回报就越少。我应该去元吗? - Jake Kurzer
2
有没有人想要一次回顾,考虑到我现在对分析器的了解? - Jake Kurzer
显示剩余10条评论
19个回答

2
我使用 xperf/ETW 来进行所有的分析需求。它有一个陡峭的学习曲线,但是非常强大。如果你在 Windows 上进行分析,那么你必须了解 xperf。我经常使用这个分析器来查找我的代码和其他人的代码中的性能问题。
在我使用的配置中:
  • xperf 每毫秒从正在执行代码的每个核心中获取 CPU 样本。采样率可以增加到 8 KHz,并且样本包括用户模式和内核代码。这允许在线程运行时找出线程正在做什么
  • xperf 记录每个上下文切换(允许完美重构每个线程使用的时间),以及当线程被切换入时的调用堆栈,以及为哪个线程准备好另一个线程的调用堆栈,允许跟踪等待链并找出为什么线程未运行
  • xperf 记录所有进程的文件 I/O
  • xperf 记录所有进程的磁盘 I/O
  • xperf 记录活动窗口、CPU 频率、CPU 电源状态、UI 延迟等信息。
  • xperf 还可以记录一个进程的所有堆分配、所有进程的虚拟分配等等。
这是很多数据,全部在一个时间轴上,适用于所有进程。Windows 上没有其他性能分析器可以做到这一点。 我已经广泛地博客介绍了如何使用 xperf/ETW。这些博客文章和一些专业的培训视频可以在这里找到: http://randomascii.wordpress.com/2014/08/19/etw-training-videos-available-now/ 如果你想知道如果不使用 xperf 会发生什么,请阅读这些博客文章: http://randomascii.wordpress.com/category/investigative-reporting/ 这些都是我在其他人的代码中发现的性能问题的故事,这些问题本应该被开发人员发现。其中包括将 mshtml.dll 加载到 VC++ 编译器中,VC++ 中的查找文件导致的拒绝服务,意外数量的客户机中的热量限制,Visual Studio 中缓慢的单步执行,硬盘驱动程序中的 4 GB 分配,PowerPoint 性能漏洞等。

2

编辑:我现在看到你在第一篇帖子中提到了这一点。该死,我从未想过我会成为那个人。

您可以使用Pin以更细粒度地检测您的代码。我认为Pin将允许您创建一个工具来计算进入函数的次数或在其中花费的时钟周期数,大致模拟VTune或CodeAnalyst之类的东西。然后,您可以削减被检测的函数,直到您的时间问题消失。


实际上,我最先想到的是PIN。实际上,有一种叫做PIN Play的东西非常完美,但它不会在英特尔以外发布。我不确定我是否记得足够多关于使用PIN来拼凑出真正好的东西,但是... - Jake Kurzer

2
我可以告诉你我每天使用的工具。
a)AMD Code Analyst
它很容易使用,能够快速了解正在发生的情况。对于大多数情况而言,这已经足够了。如果你有像图形引擎、视频编解码器等重操作循环时,它将向你提供关于CPU流水线的信息,但这种情况比较少见。
b)VTune.
它与vs2008非常好地集成在一起。当你确定了热点时,需要采样不仅时间,还需要采样其他内容,例如缓存丢失和内存使用情况。这是非常重要的。设置一个采样会话并编辑属性。我总是进行时间、内存读写和缓存丢失(三次不同运行)的采样。
但是,除了工具之外,你需要获得性能分析方面的经验。这意味着了解CPU/内存/PCI如何工作。因此,这是我的第三个选择。
c)单元测试
这对于开发需要极高性能的大型应用程序非常重要。如果你无法将这个应用程序分成几个部分,那么跟踪CPU使用情况将会很困难。我不测试所有的用例和类,但我有硬编码的执行和带有重要功能的输入文件。
我的建议是在几个小测试中使用随机采样,并尝试标准化配置文件策略。

AMD Code Analyst在我的开发环境中不稳定,而VTune明确不支持它。 :S - Jake Kurzer

1

只是顺便提一下,虽然它不是完整的分析器: 如果你只需要找到挂起的事件循环,并且处理一个事件需要很长时间,那么在Qt中使用临时工具就很简单。这种方法可以轻松扩展,以跟踪每个事件处理所需的时间,以及这些事件是什么等信息。它不是通用的分析器,而是一个以事件循环为中心的分析器。

在Qt中,所有跨线程信号槽调用都通过事件循环传递,定时器、网络和串口通知以及所有用户交互也是如此。因此,观察事件循环是了解应用程序花费时间的重要步骤。


1
我刚刚完成了CxxProf的第一个可用版本,这是一个便携式手动插装C++分析库。
它实现了以下目标:
  • 易于集成
  • 在编译时轻松删除lib
  • 在运行时轻松删除lib
  • 支持多线程应用程序
  • 支持分布式系统
  • 尽可能减少对性能的影响
这些要点摘自项目维基,请查看更多详情。 免责声明:我是CxxProf的主要开发人员

0

0

DevPartner最初由NuMega开发,现在由MicroFocus分发,曾经是性能分析和代码分析(例如内存和资源泄漏)的首选解决方案。 我最近没有尝试过它,所以不能保证它会对您有所帮助;但我曾经取得了出色的成果,因此这是一种备选方案,我考虑重新安装它来提高我们的代码质量(他们提供14天试用期)


0

虽然你的操作系统是Win7,但程序不能在XP下运行? 那么在XP下进行性能分析,结果应该对Win7有所提示。


当然可以,但这需要购买一个许可证,而该产品可能永远不会很好地支持您所需的开发环境,或者可能需要几年时间才能做到。1.5k是一笔很大的赌注,再加上映像和部署XP框的时间成本。 - Jake Kurzer

0

这里列出了很多性能分析工具,我自己试用了其中的几个 - 但最终我还是基于这个编写了自己的工具:

http://code.google.com/p/high-performance-cplusplus-profiler/

当然,这需要您修改代码库,但它非常适合缩小瓶颈范围,应该适用于所有x86(可能在多核框中存在问题,即它使用rdtsc,但这仅用于指示性计时 - 所以我发现它对我的需求足够了..)


该项目的副本位于 https://github.com/michael-mayes/high-performance-cplusplus-profiler,其中包含描述信息,请参见 https://floodyberry.wordpress.com/2009/10/07/high-performance-cplusplus-profiling/。 - osgx

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