关于qt:超越堆栈采样:C ++ Profilers

Beyond Stack Sampling: C++ Profilers

黑客的故事

日期是2010年2月12日。圣诞节前的几天已经不见了,作为一名Windows程序员,我几乎碰到了一个主要的障碍。我一直在使用aqtime,我尝试过困倦、闪亮和非常困倦,正如我们所说,vtune正在安装。我曾经尝试过使用VS2008分析器,它受到了积极的惩罚,而且常常是无意识的。我使用了随机暂停技术。我检查过呼叫树。我已经启动了函数跟踪。但令人痛心的事实是,我正在使用的应用程序超过了一百万行代码,可能还有价值一百万行的第三方应用程序。

我需要更好的工具。我读过其他的主题。我已经尝试了每个主题中列出的每个分析器。只是必须有比这些愚蠢而昂贵的选择更好的选择,或是几乎没有任何收益的滑稽的大量工作。更为复杂的是,我们的代码是重线程的,运行了许多qt事件循环,其中一些循环非常脆弱,以致于由于时间延迟而在重检测下崩溃。不要问我为什么要运行多个事件循环。没人能告诉我。

在Windows环境中,是否还有其他选择?有什么比我试过的那一长串坏工具更好的吗?是否有任何设计用于与qt集成,或者与队列中事件的有用显示相集成?

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

  • 相当好!深度递归有一些问题,但在这些情况下调用图是正确的,可以用来清除可能存在的任何混乱。不是一个完美的工具,但值得尝试。它可能适合你的需要,而且在大多数时候对我来说肯定是足够好的。
  • 调试模式下的随机暂停攻击:时间不够。一个好的工具,但不是一个完整的解决方案。
  • 平行工作室:核选择。突兀的,怪异的,疯狂的强大。我认为你应该加快30天的评估,看看是否合适。真是太酷了。
  • AMD代码分析师:很棒,易于使用,非常容易崩溃,但我认为这是一个环境问题。我建议你试试,因为它是免费的。
  • 卢克·斯塔克沃克:在小项目上工作很好,有点想让它在我们的项目上工作。不过,还是有一些不错的效果,它肯定能代替我的个人任务。
  • purifyplus:不支持Win-X64环境,尤其是Windows7。否则很好。我在其他部门的一些同事对此发誓。
  • VS2008事件探查器:在功能跟踪模式下以所需分辨率在100+Gigs范围内生成输出。有利的一面是,产生可靠的结果。
  • gprof:要求gcc甚至是适度有效的。
  • vtune:vtune的w7支持近乎犯罪。其他方面都很好
  • 我需要自己的工具,所以这是最后的选择。
  • 困倦Verysleepy:对较小的应用程序有用,但在这里失败了。
  • EasyProfiler:如果您不介意用一些手动注入的代码来指示在哪里进行检测,那就不错了。
  • Valgrind:*只有尼克斯,但在那种环境下很好。
  • oprofile:仅限Linux。
  • 他们射杀野马。

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

  • XPerf:
  • Glowcode:
  • Devpartner:

笔记:目前的英特尔环境。VS2008,Boost库。QT 4 +。以及他们中最糟糕的嗡嗡声:通过Trolltech的Qt/MFC集成。


现在:差不多两周后,我的问题似乎解决了。多亏了各种各样的工具,包括清单上几乎所有的东西和我的一些个人技巧,我们发现了主要的瓶颈。然而,我将继续测试、探索和尝试新的简介以及新技术。为什么?因为我欠你们的,因为你们摇滚。它确实会让时间线慢一点,但我仍然很兴奋继续尝试新的工具。

简介在许多其他问题中,最近一些组件被切换到了不正确的线程模型,由于我们下面的代码突然不再是多线程的,这导致了严重的挂起。我不能说更多,因为这违反了我的保密协议,但我可以告诉你,这将永远不会被偶然的检查,甚至正常的代码审查发现。如果没有侧写、电话记录和随意的停顿,我们仍然会对天空中美丽的蓝色弧线大喊大叫。谢天谢地,我和一些我见过的最好的黑客一起工作,我可以读到一首充满伟大工具和伟大人物的令人惊叹的诗。

先生们,我非常感激你们,我唯一的遗憾是我没有足够的代表来奖励你们每一个人。


第一:

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

CPU采样探查器每N条指令获取一个堆栈跟踪。此技术将显示您的代码中CPU绑定的部分。如果这是你应用程序中的瓶颈,那就太棒了。如果您的应用程序线程将大部分时间花在互斥上,那就不太好了。

时间采样探查器每N微秒获取一个堆栈跟踪。这种技术将集中在"慢"代码上。原因是CPU限制、阻塞IO限制、互斥限制还是缓存抖动代码部分。简而言之,任何一段代码都会减慢应用程序的速度。

因此,如果可能的话,特别是在分析线程代码时,请使用时间采样探查器。

第二:

采样分析器生成大量数据。数据是非常有用的,但往往太多而不容易有用。在这里,配置文件数据可视化工具帮助很大。我找到的用于配置文件数据可视化的最佳工具是gprof2dot。不要让这个名字迷惑了您,它处理各种采样分析器输出(AQTime、Sleepy、XPerf等)。一旦可视化指出了有问题的函数,请跳回到原始配置文件数据,以更好地提示实际原因是什么。

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

一些提示可以让gprof2dot生成好的输出。

  • 我在图表上使用0.001的--skew,这样我就可以很容易地看到热代码路径。否则,int main()将主导图形。
  • 如果你用C++模板做任何疯狂的事情,你可能想添加EDCOX1,2。这一点尤其适用于Boost。
  • 我使用oprofile生成我的采样数据。要获得良好的输出,我需要将其配置为从第三方和系统库中加载调试符号。一定要做同样的事情,否则你会看到CRT占用了你应用程序20%的时间,而实际发生的事情是malloc正在破坏堆并吞噬15%。


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

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

然后我通过点击"暂停"来采集大约10个样本,这让我等待。我使用^a、^c和^v将它们复制到记事本中,以供参考。然后我研究每一个问题,试图弄清楚在那个时候要完成的过程中是什么。

如果它试图在2个或更多的样本上完成某项工作,而这项工作并不是绝对必要的,那么我发现了一个活的问题,我大致知道修复它可以节省多少钱。

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

我发现的各种事物的例子:

  • 在启动过程中,从dll资源中提取国际化字符串的过程中,它可能有30层深。如果检查实际字符串,很容易发现这些字符串实际上不需要国际化,就像用户从未实际看到过的字符串一样。

  • 在正常使用过程中,一些代码在某些对象中无意地设置了一个修改过的属性。该对象来自一个超类,它捕获更改并触发通知,这些通知在整个数据结构中波动,操作UI,以难以预见的方式创建和解除对象保护。这可能会发生很多-通知的意外后果。

  • 逐行、逐单元填写工作表。事实证明,如果您同时构建行,从一个值数组中,它会快得多。

另外,如果你是多线程的,当你暂停它时,所有线程都会暂停。查看每个线程的调用堆栈。机会是,只有一个是真正的罪魁祸首,而其他人却无所事事。


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


您有MFC OnIdle功能吗?在过去,我有一个近乎实时的应用程序,我必须解决的是,当设置为19.2公里的速度时,串行数据包丢失,而Pentiumd应该能够跟上。唯一的功能就是杀人。我不确定Qt是否有这个概念,但我也会检查一下。


我已经成功地将purifyplus用于Windows。虽然它并不便宜,但IBM提供的试用版有点残缺。使用Quantify进行分析只需要PDB文件和/Fixed:No.链接。唯一的缺点是:不支持Win7/64。


vs分析器——如果它生成如此大的文件,那么您的采样间隔可能太频繁了?试着降低它,因为你可能有足够的样品。

理想情况下,确保在实际操作问题区域之前不采集样本。所以从暂停收集开始,让程序执行其"慢速活动",然后开始收集。您最多只需要收集20秒。在此之后停止收集。

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


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

不过,根据你最近的评论,听起来你至少取得了一些进展。也许这个工具可以为您提供一些有用的度量标准。如果没有其他东西,它有一些真正的珀迪图表和图片:p


检验XPRF

这是微软提供的免费、非侵入性和可扩展的profiler,由微软开发用于分析Windows。


另外两个工具建议。

卢克·斯塔克沃克有一个可爱的名字(即使我觉得这个名字有点难用),它不会花你任何钱,你会得到源代码。它也声称支持多线程程序。所以它肯定值得一转。

网址:http://lukestackwalker.sourceforge.net/

还有glowcode,我已经指出它值得使用:

网址:http://www.glowcode.com/

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


如果您怀疑事件循环,是否可以重写qcoreapplication::notify()和dosome手动分析(将发送方/事件映射到计数/时间)?

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

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

只是一个想法。


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

a)AMD代码分析员

  • 这很简单,它会让你快速了解正在发生的事情。大部分时间都可以。
  • 使用AMD的CPU,它将告诉您有关CPU管道的信息,但只有当您有很重的循环(如图形引擎、视频编解码器等)时,才需要这样做。

b)VTUNE。

  • 它在VS2008中集成得很好

  • 在知道热点之后,您不仅需要对时间进行采样,还需要对缓存未命中和内存使用等其他情况进行采样。这很重要。设置采样会话,然后编辑属性。我总是对时间、内存读/写和缓存未命中进行采样(三次不同的运行)

但不仅仅是工具,您还需要获得分析方面的经验。这意味着要理解CPU/memory/pci是如何工作的…所以,这是我的第三个选择

c)单元测试

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

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


编辑:我看到你在第一篇文章中提到过这个。妈的,我从没想过我会是那个人。

您可以使用pin以更细的粒度检测代码。我认为pin可以让你创建一个工具来计算你输入一个函数的次数或者你在那里花费了多少时钟信号,粗略地模仿类似于vtune或者codeanalyst的东西。然后您可以去掉哪些函数被检测,直到您的计时问题消失。


我刚刚完成了CXPROF的第一个可用版本,一个用于C++的便携式手动仪表剖析库。

它实现了以下目标:

  • 易于集成
  • 在编译期间轻松删除lib
  • 在运行时轻松删除lib
  • 支持多线程应用程序
  • 支持分布式系统
  • 尽量减少影响

这些点是从项目wiki中提取的,请查看那里了解更多详细信息。

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


我使用xperf/etw来满足我所有的分析需求。它有一个陡峭的学习曲线,但非常强大。如果您在Windows上进行分析,那么您必须了解xperf。我经常使用这个分析器在我的代码和其他人的代码中发现性能问题。

在我使用它的配置中:

  • xperf从每个执行代码的核心获取CPU样本ms.采样率可以增加到8kHz包括用户模式和内核代码。这样可以发现线程正在运行
  • 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/researchive-reporting/这些是我在其他人的代码中发现的性能问题的故事,开发人员应该发现这些问题。这包括加载到vc++编译器中的mshtml.dll,在vc++文件中查找的拒绝服务,在数量惊人的客户机中进行热节流,在Visual Studio中单步执行缓慢,在硬盘驱动程序中分配4 GB,PowerPoint性能错误等等。


抛开它,即使它不是一个全面的探查器:如果您所要做的只是挂起的事件循环,需要花费很长的时间处理一个事件,那么一个特别的工具在qt中是很简单的事情。这种方法可以很容易地扩展,以跟踪每个事件处理需要多长时间,以及这些事件是什么,等等。它不是一个通用的分析器,而是一个以事件循环为中心的分析器。

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


我使用轨道分析器,简单,开源和强大!https://orbitprofiler.com网站/


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


虽然您的操作系统是Win7,但程序不能在XP下运行?在xp下对它进行分析怎么样,结果应该是win7的提示。


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

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

当然,它确实要求您修改代码库,但它非常适合缩小瓶颈,应该适用于所有X86s(可能是多核盒的问题,即它使用RDTSC,但是-这纯粹是为了指示时间-所以我发现它足以满足我的需要….