当前位置:  开发笔记 > 编程语言 > 正文

人们可以使用分析器,但为什么不停止程序呢?

如何解决《人们可以使用分析器,但为什么不停止程序呢?》经验,为你挑选了12个好方法。

如果某个东西正在使单线程程序占用,比如10倍,那么就可以在其上运行一个分析器.您也可以通过"暂停"按钮暂停它,您将看到它正在做什么.

即使它比它应该慢了10%,如果你停止它多次,不久你会看到它反复做不必要的事情.通常问题是在堆栈中间某处不是真正需要的函数调用.这不能衡量问题,但确实找到了.

编辑:反对意见主要假设您只采取1个样本.如果你是认真的,请采取10.任何一行代码,导致一定比例的浪费,如40%,将平均出现在该部分样本的堆栈上.瓶颈(单线程代码)无法隐藏它.

编辑:为了表明我的意思,许多反对意见的形式是"没有足够的样本,所以你看到的可能完全是虚假的" - 关于机会的模糊观点.但是,如果任何可识别的描述,不仅仅是在常规或常规活动中,在30%的时间内有效,那么在任何给定样本上看到它的概率是30%.

然后假设只采集了10个样本.在10个样本中看到问题的次数遵循二项分布,并且看到它0次的概率是.028.看到它1次的概率是.121.2次,概率为.233,而3次则为.267,之后下降.由于看到它少于两次的概率是.028 + .121 = .139,这意味着看到它两次或更多次的概率是1 - .139 = .861.一般规则是,如果您看到可以修复两个或更多样本的内容,则值得修复.

在这种情况下,在10个样本中看到它的机会是86%.如果你是14%没有看到它的人,那就去做更多的样品.(如果样本数量增加到20,那么两次或多次观察的几率会增加到99%以上.)所以它没有经过精确测量,但已经准确找到了,重要的是要了解它它可能很容易成为分析器无法实际找到的东西,例如涉及数据状态的东西,而不是程序计数器.



1> krosenvold..:

在服务器运行Java它始终是一个巧妙的方法做2-3快速Ctrl- BreaksS IN一行,并得到所有正在运行的线程的2-3 threaddumps.只需查看所有线程"在哪里",就可以非常快速地找出性能问题所在.

这项技术可以在2分钟内揭示比我所知的任何其他技术更多的性能问题.


请注意,这与*hprof`works的"cpu = samples"功能完全相同*.它会定期唤醒(默认为10ms)并记录每个线程的当前堆栈跟踪.如果你发现难以每次按ctrl-break 100次,那就很方便;-).
@sleske:1)这是一个问题,因为它会稀释不相关的样本.2)好.3)即如果你最大的问题是非常小,为什么还要优化?我的经验是,当你认为没有大问题时,实际上(http://stackoverflow.com/questions/926266/performance-optimization-strategies-of-last-resort/927773#927773).4)参见(http://stackoverflow.com/questions/1777556/alternatives-to-gprof/1779343#1779343)第3点.我确信hprof是一个很好的工具.Zoom也是如此.我需要有效,而不是很好.

2> Paul Tomblin..:

因为它有时会起作用,有时它会给你完全错误的答案.分析器在找到正确答案方面有更好的记录,而且通常可以更快地到达那里.


@mike你会被有多少人关心而感到惊讶.人们有全职工作或使用分析软件.在许多公司和应用程序中,它是至关重要的,当景观变得越来越大@Paul就是钱.
在我正在进行的那些程序中,在得到任何有意义的结果之前,我必须暂停大约一千次.
未敢苟同.如果一个陈述出现在N个样本的X%上,那么如果你能摆脱它,你将节省X%的时间.当然,如果N很大,你会更准确地知道X,但是谁在乎呢?
保罗,我们应该具体了解程序的类型.我有几次烘烤,从未失望过.如果您在运行时(而不是等待)采集大量样本,并且找不到任何要优化的样本,那么您的代码就非常不寻常了.
@Paul,对于档案馆 - 你能更详细地描述一下你正在研究的程序,所以我们可以了解一下我们可能会抓住分析器而不是查看多个堆栈轨迹的区域吗?
你真的试过这个吗?它的工作原理非常简单.如果一个指令在X%的时间内在调用堆栈上,那么删除它将保存那么多.保证.显示指令的样本数量的期望值为X%,简单明了.
在它之前和之后定时给出足够的准确性.
正如我在您对原始帖子的评论中暗示的那样,我的大多数编程都是高度线程化的.此方法不适用于此,但分析器可以.

3> JesperE..:

手动执行此操作实际上不能称为"快速"或"有效",但有几种分析工具可以自动执行此操作; 也称为统计分析.


魔鬼的细节.这不仅仅是采取重要的样本,而是记录的内容以及如何进行总结.您需要在每个样本上记录整个调用堆栈.然后,您需要样本中的每个语句(不是函数,语句),它出现的样本分数.
我很高兴他们终于要去做了.我希望他们也提高我认为最重要的统计数据的可见性 - 包含每个陈述的样本的一部分(在感兴趣的区间内).太糟糕了,你需要Vista.
@Mankarse:重新尝试重点来说明问题.你想做什么:A)做出精确的测量或B)找到多汁的瓶颈?(我敢打赌,你认为B需要A.)如果存在瓶颈,1)50%,2)25%,3)12.5%和4)6.25%的时间,修复*所有*它们会给你16倍的加速.如果你错过*他们中的任何一个*你得到8倍或更少.现在,可以测量每一个吗?...
@Mankarse:......这是一个很长的赌注,但是如果你拿10个样本并且*研究它们(不仅仅是计算它们),瓶颈(1)就会盯着你们5个人的脸.(那么你需要其他一千个样本?)如果你修复它,重复一遍,瓶颈(2)会做同样的事情*.这就是你如何获得所有**瓶颈,而不是错过任何瓶颈.

4> Crashworks..:

Callstack采样是一种非常有用的分析技术,特别是在查看可能在任意数量的地方花费时间的大型复杂代码库时.它具有通过挂钟时间来测量CPU使用率的优势,这对交互性很重要,并且通过每个样本获取callstack可以让您了解调用函数的原因.我经常使用它,但我使用自动化工具,例如Luke Stackwalker和OProfile以及各种硬件供应商提供的东西.

我更喜欢自动化工具而不是手动采样的原因是我的工作是统计能力.当你有一个函数占用40%的运行时间时,手动抓取十个样本是很好的,因为平均来说你会得到四个样本,并且总是至少有一个样本.但是当你有一个平面轮廓时,你需要更多的样本,有数百个叶子函数,没有超过运行时间的1.5%.

假设你有一个有许多不同种类鱼类的湖泊.如果湖中40%的鱼是鲑鱼(60%是"其他一切"),那么你只需要钓到十条鱼就知道湖里有很多鲑鱼.但如果你有数百种不同种类的鱼,每种鱼的种类不超过1%,你需要捕获超过10条鱼,才能说"这个湖是0.8%的鲑鱼和0.6%的鳟鱼".

同样在我工作的游戏中,有几个主要的系统,每个系统在数百个不同的实体中调用数十个函数,所有这些都发生在每秒60次.其中一些函数的时间漏斗进入常见操作(如malloc),但大多数都没有,并且在任何情况下都没有单个叶子每帧占用超过1000μs.

我可以看看后备箱功能和观望,"我们花了我们对碰撞时间的10%",但是这不是非常有帮助:我需要确切知道哪里发生碰撞,所以我知道去挤它的功能.只是"少做碰撞"只会让你到目前为止,特别是当它意味着抛弃功能时.我宁愿知道"我们在八叉树的狭窄相位中对缓存未命中平均花费600μs/帧,因为魔法导弹移动得如此之快并触及大量细胞,"因为那时我可以追踪到确切的修复:无论是更好的树,还是更慢的导弹.

如果比如说有20%的大块,那么手动取样stricmp就没问题,但我们的配置文件并非如此.相反,我有数百个功能,我需要从帧的0.6%到帧的0.4%.我需要每50μs功能削减10μs,每秒调用300次.为了达到这种精度,我需要更多样品.

但从本质上讲,Luke Stackwalker所做的就是你所描述的:每毫秒左右,它会暂停程序并记录callstack(包括IP的精确指令和行号).有些程序只需要成千上万的样本进行有用的分析.

(当然,我们之前已经讨论过这个问题,但我认为这是一个总结辩论的好地方.)


我同情你的约束.当我听到所有大的性能错误被压扁时,我也很怀疑,因为"最先进的"是使用分析器,他们错过了东西,大的东西,因为他们有选择偏见,说问题特别严重地方 - 热点.如果他们说"没有大问题"他们真的说"我们没有发现任何问题".(我并没有断言那里的大问题,比如矢量类的选择,一定很容易解决,只是它可以毫无疑问地被确定为成本很高,与替代方案相比.)
我刚刚在第一次下载你给出的链接时阅读了ppt.我必须说,这是非常令人印象深刻的,但是它可以解决您使用上述工具找到的各种问题.宏观优化的形式并不多.事实上,这些游戏往往是CPU,而不是GPU,这让我怀疑还有改进的空间,可能还有很多.

5> andy..:

程序员实际做的事情和他们推荐别人做的事情之间存在差异.

我知道有很多程序员(包括我自己)实际上使用这种方法.它只能帮助找到最明显的性能问题,但它快速而且肮脏且有效.

但我不会真的告诉其他程序员这样做,因为解释所有注意事项需要我太长时间.基于这种方法得出不准确的结论太容易了,并且在很多领域它根本不起作用.(例如,该方法不会显示由用户输入触发的任何代码).

就像在法庭上使用谎言探测器或"goto"声明一样,我们不建议您这样做,即使它们都有它们的用途.


我很高兴你使用它.我想这需要一些练习.这肯定需要解释.我从来没有让它给我错误的信息,而且几乎没有明显的信息.在快速代码上,比如用户输入,你需要用一个临时外循环来填充它.

6> DanO..:

我对双方的宗教基调感到惊讶.

分析很棒,当你可以做到时,它肯定会更加精致和精确.有时你不能,并且有一个可靠的备份是很好的.暂停技术就像你的电动工具距离太远或者餐馆用完时使用的手动螺丝刀.

这是一个简短的真实故事.一个应用程序(一种批处理任务)已经在生产中运行了六个月,突然之间运营商正在打电话给开发人员,因为它"太慢了".它们不会让我们在生产中附加采样分析器!您必须使用已安装的工具.在不停止生产过程的情况下,只需使用 Process Explorer(操作员已在机器上安装),我们就可以看到线程堆栈的快照.您可以浏览堆栈的顶部,使用回车键将其关闭,然后通过另一次鼠标单击获取另一个快照.您可以每隔一秒钟轻松获取样本.

不需要花很长时间才能看到堆栈的顶部是否经常出现在数据库客户端库DLL中(等待数据库),或者在另一个系统DLL中(等待系统操作),或实际上在某些方法中申请本身.在这种情况下,如果我没记错的话,我们很快就注意到应用程序在系统DLL文件调用中读取或写入网络文件的次数为8次.当然最近的"升级"改变了文件共享的性能特征.如果没有快速,肮脏和(系统管理员认可的)方法来查看应用程序在生产中所做的事情,我们将花费更多时间来测量问题,而不是纠正问题.

另一方面,当性能要求超出"足够好"以真正推动信封时,分析器变得至关重要,以便您可以尝试从所有紧密结合的前十或二十个热点中减少周期.即使您只是想在项目期间保持适度的性能要求,当您可以获得正确的工具来帮助您进行测量和测试,甚至将它们集成到您的自动化测试过程中时,它可以提供极大的帮助.

但是当电源耗尽(可以这么说)并且电池耗尽时,很清楚如何使用那把手动螺丝刀.

所以直接回答:知道你可以从停止程序中学到什么,但也不要害怕精密工具.最重要的是知道哪些工作需要哪些工具.


"宗教基调" - 哎哟!Process Explorer - 听起来很棒,现在不只是看堆栈的顶部."金块"处于中间位置.我同意剖面仪是精密工具 - 错误的精确度.他们精确地测量时间,但是(如果他们采取并保留堆栈样本)他们实际上知道问题的位置具有高精度,但他们没有向你显示,这就是你正在寻找的.

7> Ryan Boucher..:

如果我们提出"为什么不能更好地了解它?"这个问题.那么答案就是主观的.据推测,为什么不能更好地了解它是因为分析提供了长期解决方案而不是当前的问题解决方案.它对多线程应用程序无效,对于花费大量时间渲染的游戏等应用程序无效.

此外,在单线程应用程序中,如果您有一个期望消耗最多运行时间的方法,并且您希望减少所有其他方法的运行时间,那么将更难确定哪些辅助方法可以集中精力一开始.

您的分析过程是一种可以接受且可行的方法,但分析为您提供了更多信息,并且可以向您显示更详细的性能改进和回归.

如果您有经过良好检测的代码,那么您可以检查的不仅仅是特定方法的时长; 你可以看到所有的方法.

通过分析:

然后,您可以在每次更改后重新运行方案,以确定性能改进/回归的程度.

您可以在不同的硬件配置上分析代码,以确定您的生产硬件是否足够.

您可以在负载和压力测试场景下分析代码,以确定信息量如何影响性能

您可以让初级开发人员更容易想象他们的更改对您的代码的影响,因为他们可以在您离开海滩或酒吧或两者时在六个月内重新分析代码.海滩酒吧,ftw.

分析更加重要,因为企业代码应该始终具有一定程度的分析,因为它给组织带来了长时间的好处.代码越重要,您的分析和测试就越多.

您的方法是有效的,另一个项目是开发人员的工具箱.它只是通过剖析而超过了它.


谢谢,瑞恩.我承认我不是探查专家.我所知道的就是我从他们的规格中看到的.我是一个大团队,人们谈论他们但不使用它们.通常我只是暂停代码几次并说"你知道你花了很多时间做这个吗?" 哎呀 - 不是故意的.
我同意你对Profilers作为一般健康监测工具的看法.为了准确找到瓶颈,他们只提供线索.他们没有指出问题(大多数).他们找到了干草堆,但这种方法可以找到针头.

8> Vineet Reyno..:

在"调试"模式下执行程序期间按下暂停按钮可能无法提供正确的数据来执行任何性能优化.说穿了,它是一种粗略的剖析形式.

如果您必须避免使用分析器,最好的办法是使用记录器,然后应用减速因子来"猜测"真正的问题所在.然而,Profilers是更好的猜测工具.

在调试模式下按下暂停按钮的原因可能无法给出应用程序行为的真实情况,因为调试器引入了可以减慢应用程序某些部分的额外可执行代码.可以参考Mike Stall的博客文章,了解调试环境中应用程序减速的可能原因.该帖子揭示了某些原因,例如断点太多,异常对象的创建,未经优化的代码等.关于未经优化的代码的部分很重要 - "调试"模式将导致大量优化(通常代码内嵌和重新被抛出窗口,启用调试主机(运行代码的过程)和IDE来同步代码执行.因此,在"调试"模式下重复执行暂停可能是一个坏主意.


你说的是真实但无关紧要的事情,因为单线程程序会花费一系列循环,你需要找出是否因为不良原因而花费了其中任何一个.修复后,它需要更少的周期,然后运行得更快.
在调试模式下,确保有开销,但它在发布模式下消失.关于内联的事情是在程序计数器所在的代码中很重要.调用堆栈越高,它没有任何区别,这就是许多问题所在.
我认为问题在于测量性能和发现性能问题之间的混淆.我建议分开这些目标.
我已经说过,如果他们对整个调用堆栈进行采样(有些人会这样做),并且如果他们告诉你,每个指令(调用或非调用)它有多少百分比的堆栈,那么分析器会有所帮助.唯一剩下的一点是,对于重大问题,需要的样本不多.

9> 小智..:

采样分析器仅在以下情况下有用

    您正在使用少量线程监视运行时.最好是一个.

    每个线程的调用堆栈深度相对较小(以减少收集样本的难以置信的开销).

    您只关心挂钟时间而不关心其他仪表或资源瓶颈.

    您尚未检测代码以进行管理和监视(因此堆栈转储请求)

    您错误地认为删除堆栈框架是一种有效的性能改进策略,无论固有成本(不包括被调用者)是否几乎为零

    您不必费心学习如何在工作中日常应用软件性能工程

    ....


@William:你真正需要做的是决定你关心的事情.如果系统在经验上"太慢",那么挂钟时间片就是要采样的东西.对于每个样本,您需要找出_why_它正在花费.在单线程程序中,堆栈通常可以告诉您,但并非总是如此,如果它是解释器或消息驱动的.如果它是多线程的,那么确定_why_可能更难,但这是你需要确定的,因为要花费更少的所需资源单位,你需要找到那些具有非必要原因的单位.

10> Tim..:

这些必须是您正在使用的一些简单示例,以便使用您的方法获得有用的结果.我无法想象一个项目,其中分析是有用的(通过任何方法),通过"快速有效"的方法可以获得不错的结果.启动和停止某些应用程序所需的时间已经使您的"快速"断言成为问题.

同样,对于非平凡的程序,您提倡的方法是无用的.

编辑:关于"为什么不是更好地知道"?

根据我的经验,代码审查避免了质量差的代码和算法,并且分析也会发现这些.如果你希望继续你的方法很棒 - 但我认为对于大多数专业人士来说,这是迄今为止尝试的事情清单,它永远不会得到积极的强化作为一个良好的时间利用.

对于小样本集来说似乎是非常不准确的,并且获得大样本集会花费大量时间用于其他有用的活动.


所以这就是场景:有一个很大的系统,而且所有这些都是通过代码审查等完成的,但仍然存在问题.探查器会告诉您哪个州和县包含问题,但堆栈采样会告诉您确切的门阶.
实际上它在更大的软件上效果更好,因为由于堆栈通常更深,所以有更多的指令,因此更多的候选者进行优化.对于需要很长时间才能启动和停止的应用程序,正是在停止时它会找出原因.
Profilers可以告诉你这个,但由于某些原因他们没有,正如我在下面的"答案"中解释的那样.
你确定吗?调用堆栈上的时间分数,每个语句(不是函数),在感兴趣的时间间隔中,按降序排序?我想有些人可以做到这一点.从我读到的内容来看,大多数都没有.

11> Thorbjørn Ra..:

堆栈跟踪快照仅允许您查看应用程序的频闪X射线.您可能需要更多累积的知识,分析器可能会给您.

诀窍在于了解您的工具并选择最适合您手头的工作.


@Thorbjørn:嗯,谁可以和你的最后一句话争论?每个工具都自动化一项技术.我的观点是,这个问题的本质是采样(和分析)堆栈的技术鲜为人知,简单且非常有效.更重要的是,人们对性能的环境态度需要重新评估.例如,如果您想精确测量性能,那很好,但如果您想提高性能,那么测量就会忽略这一点.

12> dove..:

如果该程序正在生产中并由付费客户或同事同时使用该怎么办?分析器允许您在没有干扰的情况下进行观察(同样,因为根据海森堡原理它也会受到一点打击).

分析还可以为您提供更丰富,更详细的准确报告.从长远来看,这将更快.


您将海森堡原则与观察者效应相混淆:http://en.wikipedia.org/wiki/Conflated
只有它被吸引到外面的世界.否则,停止它不会改变其行为.
我也喜欢量子物理,你可能适合缓存未命中等问题.我几乎总能找到的只是愚蠢的代码,通常是由太多的抽象层引起的,并且40倍的加速是常见的.
这是一个可爱的概念,但它是一个转移.它根本不适用于此.
推荐阅读
oDavid_仔o_880
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有