超越堆栈采样:C++ Profilers

Jak*_*zer 145 c++ optimization profiler qt profiling

黑客的故事

日期是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 + gigs范围内的输出.从好的方面来说,产生可靠的结果.
  • GProf:要求GCC甚至适度有效.
  • VTune:VTune的W7支持犯罪边界.否则很棒
  • 密码:我需要破解自己的工具,所以这是最后的手段.
  • Sleepy\VerySleepy:对于较小的应用程序很有用,但在这里让我失望.
  • EasyProfiler:如果您不介意手动注入一些代码来指示仪器的位置,那就不错了.
  • Valgrind:*nix only,但是当你在那个环境中时非常好.
  • OProfile:仅限Linux.
  • Proffy:他们拍野马.

我没试过的建议工具:

  • XPerf:
  • Glowcode:
  • Devpartner:

备注:目前 英特尔环境.VS2008,提升库.Qt 4+.他们所有人的悲惨态度:通过trolltech进行Qt/MFC整合.


现在:差不多两周后,看起来我的问题已经解决了.感谢各种工具,包括列表中的几乎所有工具以及我的一些个人技巧,我们发现了主要的瓶颈.但是,我将继续测试,探索和尝试新的分析器以及新技术.为什么?因为我欠你们的,因为你们摇滚.它确实减慢了时间线,但我仍然非常高兴继续尝试新工具.

概要
在许多其他问题中,最近已将许多组件切换到不正确的线程模型,由于我们下面的代码突然不再是多线程的,因此导致严重的挂起.我不能说更多,因为它违反了我的保密协议,但我可以告诉你,通过临时检查甚至正常的代码审查都不会发现这种情况.如果没有分析器,调用图和随机暂停,我们仍然会在美丽的蓝色天空中尖叫着我们的愤怒.值得庆幸的是,我与一些我见过的最好的黑客合作,我可以获得一个充满伟大工具和优秀人才的惊人"诗歌.

Gentlefolk,我非常欣赏这一点,并且唯一的遗憾是我没有足够的代表来奖励你们每个人.我仍然认为这是一个重要的问题,要比我们到目前为止得到的更好的答案.

结果,在接下来的三个星期的每周,我将提供我能负担得起的最大奖金,并用我认为不是常识的最好的工具授予它答案.三个星期后,如果你原谅我的惩罚,我们希望已经积累了一些关于剖析器的确切概况.

外卖
使用分析器.他们对Ritchie,Kernighan,Bentley和Knuth来说已经足够了.我不在乎你认为你是谁.使用分析器.如果你得到的那个不起作用,找另一个.如果你找不到一个,代码一.如果你不能编码一个,或者它是一个小挂机,或者你只是卡住,使用随机暂停.如果一切都失败了,请聘请一些研究生来敲打一个剖析器.


更长远的观点
所以,我认为写一些回顾可能会很好.我选择与Parallel Studios广泛合作,部分原因是它实际上是建立在PIN工具之上的.在与一些研究人员进行了学术交流之后,我觉得这可能是一些品质的标志.谢天谢地,我是对的.虽然GUI有点可怕,但我发现IPS非常有用,尽管我不能轻易地为每个人推荐它.至关重要的是,没有明显的方法可以获得线级命中数,这是AQT和其他一些分析器提供的,我发现它对于检查分支选择率等非常有用.在网上,我也喜欢使用AQTime,我发现他们的支持非常敏感.同样,我必须符合我的建议:他们的许多功能都不能很好地工作,其中一些功能在Win7x64上完全崩溃.XPerf的表现也令人钦佩,但是对于在某些类型的应用程序上获得良好读取所需的采样细节来说,这是非常缓慢的.

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

def*_*ode 64

第一:

时间采样分析器比CPU采样分析器更强大.我对Windows开发工具并不是很熟悉,所以我不知道哪些是哪种.大多数分析器都是CPU采样.

CPU采样分析器每N条指令抓取一次堆栈跟踪.
此技术将揭示代码中受CPU限制的部分代码.如果这是您应用程序中的瓶颈,那就太棒了.如果您的应用程序线程花费大部分时间来争用互斥锁,那就不那么好了.

时间采样分析器每N微秒抓取一次堆栈跟踪.
这种技术将归零"慢"代码.原因是否是CPU绑定,阻止IO绑定,互斥绑定或缓存颠簸部分代码.简而言之,任何一段代码都会减慢你的应用程序的速度.

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

第二:

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

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

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

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

  • 我问过这个问题[Linux time sample based profiler](http://stackoverflow.com/q/2449159/28817).OProfile最终是基于获取时间的采样.它们可以产生非常高质量的输出,所以一旦他们添加了这个功能,我就会使用它们.除此之外,我有一个朋友一起破解gdb + backtrace解决方案进行分析.非常hacky,但确实找到了瓶颈. (2认同)

Mik*_*vey 16

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

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

然后,在让我等待的时候,我会通过点击"暂停"来拍摄大约10个样本.我使用^ A,^ C和^ V将它们复制到记事本中,以供参考.然后我研究每一个,试图找出当时试图完成的过程.

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

有些事情你并不真正需要知道,像精确的百分比并不重要,什么那张里面的第三方代码并不重要,因为你不能做任何事情.你可以做一些事情是一套丰富的代码调用点,你可以在每个堆栈样品修改显示.那是你快乐的狩猎场.

我发现的事物的例子:

  • 在启动期间,在尝试从DLL资源中提取国际化字符串的过程中,它可以是大约30层深.如果检查实际的字符串,很容易发现字符串实际上不需要国际化,就像它们是用户从未真正看到的字符串一样.

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

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

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

  • QT/MFC?难道不应该产生具有3个头部的突变儿童来回摇滚,同时呼唤他们听到最愚蠢的想法的每个想法吗?错误...我离题了...如果您正在使用任何MFC套接字类,请立即重写套接字代码然后进行配置.CSocket代码中有很多地方使用WaitForSingleObject的消息循环版本,我发现它可以消除性能.对于我的生活,我不记得等待功能的名称......:/ (5认同)
  • QTMFC整合?哦,很棒,你有**复杂**和**邪恶**,你还没有得到特定于应用程序的代码. (3认同)
  • @Jake:不太舒服,但这是图灵普遍性的荣耀.任何语言,无论多高或低,都等同于其无限的滥用能力. (3认同)
  • 评论?评论?这是斯巴达!我...抱歉,不知道那是从哪里来的.不,代码使Klingon Opera看起来可读,而且它的记录也很好.实际上,我认为它的记录要少得多......哦,上帝. (2认同)
  • 哦,上帝,相信我,它就像你想的那样棘手. (2认同)

Ada*_*eld 8

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

  • @Jake:我不确定你的意思.AMD CodeAnalyst不需要AMD芯片,它应该适用于大多数x86或x64(又名x86-64/IA-64/AMD64)芯片,包括英特尔芯片. (4认同)

Jim*_*imR 7

你有MFC OnIdle功能吗?在过去,我有一个近乎实时的应用程序,我必须修复,当设置为19.2K的速度,PentiumD应该能够跟上时,丢弃串行数据包.OnIdle功能就是杀人的东西.我不确定QT是否有这个概念,但我也会检查它.

  • 我们实际上有一个OnIdle,并且由于我们的QTMFC集成,它正在流经QT ev..e ... eve ...事件循环.哦,G'd. (2认同)