超越堆栈采样:C ++ Profiler

黑客的故事

日期是12/02/10。 圣诞节前的日子正在流逝,我几乎成为一个Windows程序员的主要障碍。 我一直在使用AQTime,我试过困了,有光泽,很困,而且正如我们所说,VTune正在安装。 我尝试过使用VS2008分析器,它一直是积极的惩罚,而且往往是无情的。 我使用了随机暂停技术。 我已经研究过调用树。 我发射了功能痕迹。 但令人痛心的事实是,我正在使用的应用程序有超过一百万行代码,可能还有价值百万的第三方应用程序。

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

在Windows环境下,Valgrind有更多的选择吗?
有没有什么比我已经尝试过的那些破碎的工具更好?
是否有任何设计与Qt集成,可能是在队列中显示事件的有用信息?

我尝试的工具的完整列表,以及斜体真正有用的工具:

  • AQTime:相当好! 在深递归中遇到一些问题,但在这些情况下调用图是正确的,并且可以用来清除您可能遇到的任何混淆。 不是一个完美的工具,但值得尝试。 它可能适合你的需求,而且大多数时候对我来说它确实足够好。
  • 调试模式下的随机暂停攻击:没有足够的时间信息。
    一个好工具,但不是完整的解决方案。
  • Parallel Studios:核选项。 突兀,怪异,疯狂的强大。 我认为你应该进行30天评估,并确定它是否合适。 它也很酷。
  • AMD Codeanalyst:精彩,易用,非常容易崩溃,但我认为这是一个环境问题。 我建议尝试一下,因为它是免费的。
  • Luke Stackwalker:在小型项目上运行良好,有点想让它适合我们的工作。 虽然有一些好的结果,并且它完全取代了我的个人任务Sleepy。
  • PurifyPlus:不支持Win-x64环境,最显眼的是Windows 7。 我在其他部门的一些同事发誓。
  • VS2008 Profiler:在功能跟踪模式下以所需的分辨率在100 +演唱会范围内产生输出。 从好的一面来看,会产生可靠的结果。
  • GProf:要求海湾合作委员会甚至是中等有效的。
  • VTune:VTune的W7支持犯罪分子。 否则优秀
  • 个人识别号码:我需要破解我自己的工具,所以这是不得已而为之的。
  • Sleepy VerySleepy:对于较小的应用程序很有用,但是在这里失败了。
  • EasyProfiler:如果您不介意一些手动注入的代码来指示仪器的位置,那就不错了。
  • Valgrind:只有nix,但是当你在那个环境中时非常好。
  • OProfile:仅限Linux。
  • Proffy:他们射野马。
  • 我还没有尝试过的建议工具:

  • XPerf:
  • Glowcode:
  • Devpartner:
  • 注:目前的英特尔环境。 VS2008,增强库。 Qt 4+。 而他们所有人的猥琐手段:通过trolltech整合Qt / MFC。


    现在:差不多两周后,看起来我的问题已解决。 感谢各种工具,包括名单上的几乎所有东西以及一些我的个人窍门,我们发现了主要瓶颈。 但是,我将继续测试,探索和尝试新的性能分析器以及新技术。 为什么? 因为我欠你们,因为你们摇滚。 它的确缩短了时间表,但我仍然非常高兴能够继续尝试新的工具。

    概要
    在许多其他问题中,最近一些组件被切换到了不正确的线程模型,由于下面的代码突然不再是多线程的,所以造成了严重的困扰。 我不能说更多,因为它违反了我的NDA,但我可以告诉你,这不会被偶然检查或甚至通过正常的代码审查发现。 没有配置文件,调用图和随机暂停,我们仍然会在美丽的蓝色天空中尖叫我们的愤怒。 值得庆幸的是,我与一些我见过的最好的黑客合作过,并且我可以访问一个非常棒的'诗歌',里面有很多伟大的工具和伟大的人物。

    绅士,我非常欣赏这一点,只有遗憾的是我没有足够的代表来奖励你们每个人。 我仍然认为这是一个重要的问题,以获得比我们目前为止所获得的更好的答案。

    因此,在接下来的三周里,每周我都会提供我能负担得起的最大奖金,并用我认为不是常识的最好工具给予答案。 三周后,如果你会原谅我的唠叨,我们希望已经积累了一个明确的个人资料。

    带走
    使用分析器。 他们对Ritchie,Kernighan,宾利和Knuth来说已经足够好了。 我不在乎你以为你是谁。 使用分析器。 如果你得到的那个不行,找另一个。 如果找不到,请输入一个。 如果你不能编码,或者是一个小的挂断,或者你只是卡住,使用随机暂停。 如果一切都失败了,请雇用一些研究生来闯出一个探查器。


    更长远的观点
    所以,我认为写一些回顾可能会很好。 我选择与Parallel Studios广泛合作,部分原因是它实际上是建立在PIN工具之上的。 与一些研究人员进行了学术交流之后,我觉得这可能是一些质量的标志。 谢天谢地,我是对的。 虽然图形用户界面有点可怕,但我发现IPS非常有用,尽管我不能很好地向大家推荐它。 关键的是,没有明显的方法可以获得行级命中计数,AQT和其他一些分析器提供的东西,而且我发现在检查分支选择率等方面非常有用。 在网络中,我也很喜欢使用AQTime,并且我发现他们的支持非常有效。 再次,我必须符合我的建议:他们的许多功能不能很好地工作,其中一些功能在Win7x64上非常容易崩溃。 XPerf的表现也令人钦佩,但对于在某些类型的应用中获得良好读取所需的采样细节而言,令人痛苦地缓慢。

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


    第一:

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

    CPU采样分析器每N条指令抓取一个堆栈跟踪。
    这种技术将揭示你的代码的CPU绑定的部分。 如果这是你应用程序的瓶颈,那真棒。 如果您的应用程序线程将大部分时间花费在互斥体上,那就不是那么好。

    时间采样分析器每隔N微秒捕获一次堆栈跟踪。
    这项技术将在“慢”代码中归零。 无论原因是CPU绑定,阻止IO绑定,互斥锁绑定还是高速缓存抖动代码段。 简而言之,任何一段代码都会减慢应用程序的性能。

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

    第二:

    采样分析器生成大量的数据。 这些数据非常有用,但通常太多容易使用。 个人资料数据可视化工具在这里非常有帮助。 我发现的用于配置文件数据可视化的最佳工具是gprof2dot。 不要让名称欺骗你,它处理各种采样分析器输出(AQtime,Sleepy,XPerf等)。 一旦可视化指出了有问题的功能,就跳回到原始配置文件数据中,以获取有关真实原因的更好提示。

    gprof2dot工具生成一个点图描述,然后将其提供给graphviz工具。 输出基本上是一个调用图,其功能通过对应用程序的影响进行颜色编码。 替代文字

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

  • 我在图上使用了0.001的--skew ,以便我可以轻松看到热门代码路径。 否则, int main()在图中占主导地位。
  • 如果你对C ++模板做了什么疯狂的事情,你可能会想添加--strip 。 Boost尤其如此。
  • 我使用OProfile生成我的采样数据。 为了获得良好的输出,我需要配置它以从我的第三方和系统库加载调试符号。 一定要这样做,否则你会发现CRT正在占用你应用程序20%的时间,而真正发生的事情是malloc正在捣毁这个堆并占用15%的时间。

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

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

    然后,在我等待的时候,我通过点击“暂停”大约10个样本。 我用^ A,^ C和^ V将它们复制到记事本中供参考。 然后,我研究每一个,试图找出当时正在努力完成的过程。

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

    有些东西你根本不需要知道,比如精确的百分比并不重要,第三方代码中的内容并不重要,因为你无法对这些内容做任何事情。 你可以做些什么是你可以在每个堆栈样本上显示的代码中丰富的调用点集。 这是你的快乐狩猎场。

    我发现的东西的例子:

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

  • 在正常使用期间,一些代码在某个对象中无意中设置了Modified属性。 该对象来自一个超级类,捕获变化并触发通知,这些通知在整个数据结构中起伏不定,操纵UI,以难以预见的方式创建和删除对象。 这可能发生很多 - 通知的意外后果。

  • 逐行填写工作表,逐个单元格。 事实证明,如果您从一组值中一次构建行,速度会快得多。

  • PS如果你是多线程的,当你暂停它时,所有线程暂停。 看看每个线程的调用堆栈。 机会是,其中只有一个是真正的罪魁祸首,而其他人是空着的。


    我在AMD CodeAnalyst上取得了一些成功。

    链接地址: http://www.djcxy.com/p/7619.html

    上一篇: Beyond Stack Sampling: C++ Profilers

    下一篇: Profile optimised C++/C code