超越堆栈抽样: C + + 分析器

黑客的故事

日期是12/02/10。圣诞节前的日子一天天过去,作为一个 Windows 程序员,我几乎遇到了一个主要的障碍。我一直在使用 AQTime,我尝试了瞌睡、闪亮和非常瞌睡,就在我们说话的时候,VTune 正在安装。我曾经尝试使用 VS2008分析器,它一直是积极的惩罚,而且经常是不理智的。我使用了随机暂停技术。我检查了呼叫树。我发射了功能追踪。但令人痛心的事实是,我正在使用的应用程序有超过100万行代码,可能还有价值100万行的第三方应用程序。

我需要更好的工具。我已经尝试了每个主题中列出的每个分析器。只是必须有比这些垃圾和昂贵的选择,或荒谬的工作量几乎没有收益更好的东西。更复杂的是,我们的代码是高度线程化的,并且运行了许多 Qt Event 循环,其中一些循环非常脆弱,以至于由于时间延迟,它们在高度仪器化的情况下崩溃。别问我为什么要运行多个事件循环。没人能告诉我。

在 windows 环境下还有其他类似 Valgrind 的选择吗?
还有什么比我已经试过的一长串破工具更好的吗?
是否设计了任何与 Qt 集成的东西,也许是一个有用的队列中事件显示?

我尝试过的工具的完整列表,以及那些在斜体字中真正有用的工具:

  • 相当不错!在深度递归方面有一些问题,但是调用图在这些情况下是正确的,并且可以用来清除您可能遇到的任何混淆。不是一个完美的工具,但值得一试。它可能适合你的需要,而且对我来说大部分时间都是足够好的。
  • 调试模式下的随机暂停攻击: 时间信息不足。
    一个好的工具,但不是一个完整的解决方案。
  • 平行工作室: 核选项。很烦人,很奇怪,还很强大。我觉得你应该去看看30天的评估看看是不是合适。真是酷毙了。
  • AMD 代码分析师: 很棒,易于使用,非常容易崩溃,但我认为这是环境的问题。我建议你试试,因为它是免费的。
  • Luke Stackwalker: 在小项目上很好用,但是在我们的项目上就有点难了。不过还是有一些不错的结果,它完全取代了瞌睡虫完成我的个人任务。
  • PurifyPlus: 不支持 Win-x64环境,尤其是 Windows 7。其他方面都很好。我在其他部门的许多同事对此深信不疑。
  • VS2008剖析器: 在函数跟踪模式下,以所需的分辨率产生100 + G 范围内的输出。从积极的一面来看,产生了可靠的结果。
  • 需要海湾合作委员会,甚至适度有效。
  • VTune: VTune 的 W7支持接近于犯罪,其他方面都很优秀
  • 我得自己动手,所以这是最后的手段。
  • Sleepy VerySleepy: 对于较小的应用程序很有用,但是在这里失败了。
  • EasyProfiler: 如果您不介意手动注入一些代码来指示仪器的位置,那么这个代码还不错。
  • 瓦尔格伦: * nix only,but very good when you’re in that environment。
  • OProfile: Linux only.
  • 他们射杀野马。

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

  • XPerf:
  • 发光代码:
  • 发展伙伴:

备注: 目前的英特尔环境。VS2008,增强库。Qt 4 + .还有最可怜的惊喜: 通过 trolltech 实现 Qt/MFC 集成。


现在: 差不多两周后,我的问题似乎解决了。多亏了各种各样的工具,包括列表中的几乎所有东西和我的一些个人技巧,我们找到了主要的瓶颈。然而,我将继续测试、探索和尝试新的侧写器和新技术。为什么?因为这是我欠你们的,因为你们太棒了。它确实延缓了一点时间线,但我仍然非常兴奋地继续尝试新的工具。

大纲
在许多其他问题中,有许多组件最近被切换到了不正确的线程模型,由于我们下面的代码突然不再是多线程的,这导致了严重的挂起。我不能说更多,因为它违反了我的保密协议,但我可以告诉你,这将永远不会发现随意检查,甚至通过正常的代码审查。如果没有侧写器,电话记录器,以及随机的连接暂停,我们仍然会在美丽的蓝色弧线天空尖叫我们的愤怒。谢天谢地,我和一些我见过的最好的黑客一起工作,我有机会进入一个充满了伟大的工具和伟大的人的神奇的宇宙。

先生们,我非常感激你们的帮助,只是很遗憾我没有足够的名声来奖励你们每一个人。我仍然认为这是一个重要的问题,需要得到一个更好的答案,而不是迄今为止我们所得到的关于 SO 的答案。

因此,在接下来的三周里,我每周都会拿出我能支付得起的最大数额的奖金,然后用我认为不是常识的最好的工具来奖励答案。三个星期后,我们就有希望获得侧写师的最终侧写,请原谅我的双关语。

外卖
用个侧写师。他们对 Ritchie Kernighan Bentley 和 Knuth 都很好。我不管你以为自己是谁。用个侧写师。如果你有一个不工作,找到另一个。如果找不到,代码1。如果你不能编写一个代码,或者只是一个小小的挂断,或者你只是卡住了,使用随机暂停。如果一切都失败了,雇几个研究生来搞定一个侧写师。


远景
所以,我觉得写一些回顾会比较好。我选择大量使用平行工作室,部分原因是它实际上是建立在 PIN 工具之上的。在与一些相关研究人员进行了学术交流之后,我觉得这可能是某种品质的标志。谢天谢地,我是对的。虽然图形用户界面有点糟糕,但我发现 IPS 非常有用,尽管我不能轻松地向所有人推荐它。至关重要的是,没有明显的方法可以获得行级别的命中计数,这是 AQT 和许多其他分析器提供的,我发现对于检查分支选择率和其他事情非常有用。在网上,我也很喜欢使用 AQTime,我发现他们的支持真的很有效。同样,我必须对我的建议进行限定: 它们的许多特性不能很好地工作,其中一些特性在 Win7x64上完全容易崩溃。XPerf 的表现也令人钦佩,但是对于在某些类型的应用程序上获得良好读数所需的采样细节来说,速度慢得令人头疼。

现在,我不得不说,我认为在 W7x64环境中分析 C + + 代码没有明确的选项,但是肯定有一些选项无法执行任何有用的服务。

11861 次浏览

我在 AMD 代码分析师上取得了一些成功。

关于 VS 分析器——如果它生成如此大的文件,也许您的采样间隔太频繁了?试着降低它,因为你可能有足够的样品反正。

最理想的情况是,确保在实际运用问题区域之前不会收集样本。因此,开始收集暂停,让你的程序做它的“缓慢活动”,然后开始收集。您最多只需要20秒的收集时间。这之后停止收集。

这将有助于减少示例文件的大小,并且只捕获分析所需的内容。

当你尝试随机暂停时发生了什么?我经常在一个怪物应用程序上用这个。你说它没有提供足够的信息,你建议你需要高分辨率。有时候人们需要一点帮助来理解如何使用它。

在 VS 下,我所做的是配置堆栈显示,这样它就不会显示函数参数,因为这会使堆栈显示完全不可读,IMO。

然后,我采取约10个样本,按“暂停”在我等待的时候。我使用 ^ A,^ C 和 ^ V 将它们复制到记事本中,以供参考。然后我研究了每一个,试图弄清楚在那个时候想要完成的过程是什么。

如果它试图在两个或更多的样本上完成某些事情,而且那个事情并不是严格必要的,那么我发现了一个活的问题,我大致知道修复它将节省多少。

有些事情你真的不需要知道,比如精确的百分比并不重要,第三方代码中发生的事情也不重要,因为你不能对 那些做任何事情。您可以对 可以修改的代码中显示在每个堆栈示例上的丰富的调用点集进行处理。那就是你的快乐猎场。

我发现的例子有:

  • 在启动过程中,在试图从 DLL 资源中提取国际化字符串的过程中,它可能有30层左右的深度。如果检查了实际的字符串,就很容易发现这些字符串并没有真正的 需要国际化,就像它们是用户实际上从未看到过的字符串一样。

  • 在正常使用过程中,某些代码在某个对象中无意中设置了一个 Amendment 属性。这个对象来自一个超类,它捕获变更并触发通知,这些通知波及整个数据结构、操纵 UI、以难以预见的方式创建和销毁对象。这种情况经常发生——通知会带来意想不到的后果。

  • 逐行逐格填充工作表。结果表明,如果从一个值数组一次性构建行,会快得多。

附言。如果您是多线程,当您暂停它时,所有线程都会暂停。查看每个线程的调用堆栈。很有可能,只有一个是真正的罪魁祸首,其他人都在闲着。

Easyprofiler -我还没有看到这里提到过它,所以不确定您是否已经看过它。在如何收集度量数据方面,它采用了略有不同的方法。使用其编译时概要文件方法的一个缺点是必须对代码库进行更改。因此,您需要知道哪里可能比较慢,并在那里插入分析代码。

不过,根据你最近的评论,听起来你至少在 一些方面取得了进展。也许这个工具可以为您提供一些有用的指标。如果没有别的东西,它有一些真正美妙的图表和图片:

您有 MFC OnIdle 函数吗?在过去,我有一个几乎实时的应用程序,我必须解决掉串行数据包时,设置在19.2 K 的速度,奔腾 D 应该能够跟上。OnIdle 函数是杀戮的关键。我不确定 QT 是否有这个概念,但我也会检查一下。

检查 XPerf

这是免费的,非侵入性和可扩展的剖析器提供的 MS 它是由微软开发的配置文件窗口。

还有两个工具建议。

Luke Stackwalker 有一个很可爱的名字(尽管对我来说有点难以接受) ,它不会让你付出任何代价,而且你会得到源代码。它还声称支持多线程程序。因此,它肯定值得一试。

Http://lukestackwalker.sourceforge.net/

还有 Glowcode,我已经指出它值得一用:

Http://www.glowcode.com/

不幸的是,我有一段时间没有做任何 PC 工作,所以我没有尝试这些。我希望这些建议能有所帮助。

DevPartner 最初由 NuMega 开发,现在由 MicroFocus 发行,曾经是分析和代码分析(例如内存和资源泄漏)的首选解决方案。 我最近还没有尝试过,所以我不能保证它会对你有所帮助; 但是我曾经用它得到了很好的结果,所以这是我考虑在我们的代码质量过程中重新安装的一个替代方案(他们提供了14天的试用期)

如果您对事件循环持怀疑态度,是否可以覆盖 应用程序: : tification ()和 dosome 手动剖析(一个或两个发送者/事件到计数/时间的映射) ?

我认为应该首先记录事件类型的频率,然后更仔细地检查这些事件(哪个对象发送它,它包含什么,等等)。跨线程的信号是隐式排队的,因此它们最终会出现在事件循环中(显然,显式的排队连接也是如此)。

我们这样做是为了在事件处理程序中捕获和报告异常,所以实际上,每个事件会经过这里。

只是个想法。

我已经成功地将 PurifyPlus用于 Windows。尽管价格不菲,但 IBM 提供了一个略有缺陷的试用版。使用 量化进行概要分析所需的全部内容是 pdb 文件和链接/FIXED: NO。唯一的缺点: 不支持 Win7/64。

编辑: 我看到你在第一篇文章中提到了这一点。该死,我从没想过我会成为那样的人。

您可以使用 别针以更细的粒度检测代码。我认为 Pin 可以让你创建一个工具来计算你输入一个函数的次数或者你在那里花费了多少时钟,粗略地模拟一些像 VTune 或者 CodeAnalyst 的东西。然后,您可以剥离哪些函数被检测,直到您的计时问题消失。

第一:

时间采样分析器比 CPU 采样分析器更加健壮。我不是很熟悉 Windows 开发工具,所以我不能说哪些是哪些。大多数分析器都是 CPU 采样。

CPU 采样分析器每执行 N 个指令就获取一个堆栈跟踪。
这种技术将显示您的代码中受 CPU 限制的部分。如果这是你申请中的瓶颈,那就太棒了。如果您的应用程序线程将大部分时间花费在互斥对象上,那就不太好了。

时间采样分析器每 N 微秒获取一个堆栈跟踪。
这种技术将集中在 “慢”代码上。无论原因是 CPU 绑定、阻塞 IO 绑定、互斥锁绑定还是缓存代码的颠簸部分。简而言之,无论哪段代码减慢了应用程序的速度,它都会脱颖而出。

因此,尽可能使用时间抽样分析器,特别是在分析线程代码时。

第二:

抽样分析器生成大量数据。这些数据非常有用,但往往太多而不容易使用。配置文件数据可视化工具在这里非常有帮助。我找到的最好的配置文件数据可视化工具是 GProf2dot。不要被这个名字骗了,它可以处理所有类型的抽样分析器输出(AQtime、 Sleepy、 XPerf 等)。一旦可视化指出了违规的功能,就跳回到原始配置文件数据,以获得更好的提示,了解真正的原因是什么。

GProf2dot 工具生成一个 点图描述点图描述,然后将其提供给 Graphviz工具。输出基本上是一个调用图,函数根据它们对应用程序的影响进行颜色编码。 alt text

一些提示,让 gProf2dot 生成好的输出。

  • 我在图上使用了0.001的 --skew,因此我可以很容易地看到热代码路径。否则,int main()将占据图的主导地位。
  • 如果您正在使用 C + + 模板做一些疯狂的事情,那么您可能需要添加 --strip。Boost 尤其如此。
  • 我使用 OProfile 生成采样数据。为了获得好的输出,我需要将其配置为从我的第三方和系统库中加载调试符号。一定要这样做,否则您将看到 CRT 占用了应用程序20% 的时间,而实际上 malloc正在清理堆并消耗15% 的时间。

我可以告诉你我每天都用什么。

A) AMD 代码分析师

  • 这很简单,而且它会让你对正在发生的事情有一个快速的概述。大部分时间都会没事的。
  • 使用 AMD CPU,它会告诉你关于 CPU 流水线的信息,但是你只有在你有重循环的时候才需要它,比如图形引擎,视频编解码器等等。

B) VTune.

  • 它在 vs2008中集成得非常好

  • 了解热点之后,您不仅需要对时间进行抽样,还需要对缓存丢失和内存使用等其他情况进行抽样。这是 非常重要。设置采样会话,并编辑属性。我总是对时间、内存读/写和缓存丢失(三次不同的运行)进行采样

但是除了工具之外,您还需要获得侧写方面的经验。这意味着要了解 CPU/内存/PCI 是如何工作的... 所以,这是我的第三个选择

C)单元测试

如果您正在开发需要巨大性能的大型应用程序,这一点非常重要。如果你不能把应用程序拆分成几个部分,就很难跟踪 CPU 的使用情况。我没有测试所有的案例和类,但是我有硬编码的执行和具有重要特性的输入文件。

我的建议是在几个小型测试中使用随机抽样,并尝试标准化配置文件策略。

虽然你的操作系统是 win7,程序不能在 xp 下运行? 将它放在 xp 下,结果应该是 win7的提示。

这里列出了很多分析器,我自己也尝试了其中的一些——但是我最终还是基于以下内容编写了自己的分析器:

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

它当然需要你修改代码库,但是它对于缩小瓶颈是完美的,应该适用于所有 x86s (可能是多核机制的问题,比如它使用 rdtsc,但是——这纯粹是指示性计时——所以我发现它足以满足我的需要。.)

我刚刚完成了 教授的第一个可用版本,这是一个用于 C + + 的可移植手动仪器分析库。

它实现了以下目标:

  • 很容易整合
  • 在编译时轻松删除库
  • 在运行时轻松删除库
  • 对多线程应用程序的支持
  • 对分布式系统的支持
  • 尽量减少冲击

这些点是从 维基项目上撕下来的,看看那里有更多的细节。

免责声明: 我是 CxxProfessor 的主要开发者

我使用 xperf/ETW 满足所有分析需求。它有一个陡峭的学习曲线,但令人难以置信的强大。如果您在 Windows 上进行概要分析,那么您必须知道 xperf。我经常使用这个分析器来查找我的代码和其他人的代码中的性能问题。

在我使用它的配置中:

  • Xperf 从每个正在执行代码的核心获取 CPU 示例 采样率可以提高到8KHz,样品 包括用户模式和内核代码 线程在运行时正在做的事情
  • Xperf 记录每个上下文 开关(允许完美重建多少时间每个 线程使用) ,加上切换线程时的调用堆栈,加上 为准备好另一个线程的线程调用堆栈,允许跟踪 并查明线程为什么没有运行
  • Xperf 记录所有进程的所有文件 I/O
  • Xperf 记录所有磁盘 I/O 从所有的过程
  • Xperf 记录哪个窗口是活动的,CPU 频率、 CPU 电源状态、 UI 延迟等。
  • Xperf 还可以记录所有 来自一个进程的堆分配,来自所有进程的所有虚拟分配 过程,以及更多。

对于所有进程来说,这是一条时间线上的大量数据。

我写过大量关于如何使用 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 中缓慢的单步执行,在硬盘驱动程序中分配4GB,Powerpoint 性能错误,等等。

尽管它不是一个成熟的分析器,但我们还是要抛弃它: 如果您所追求的只是处理一个事件需要很长时间的挂起事件循环,那么 临时工具临时工具在 Qt 中就很简单了。可以很容易地扩展这种方法,以跟踪每个事件需要多长时间处理,以及这些事件是什么,等等。它不是一个通用的分析器,而是一个以事件循环为中心的分析器。

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

我使用轨道剖析器,简单,开源和强大