如果某个东西正在使单线程程序占用,比如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%以上.)所以它没有经过精确测量,但已经准确找到了,重要的是要了解它它可能很容易成为分析器无法实际找到的东西,例如涉及数据状态的东西,而不是程序计数器.
在服务器运行Java它始终是一个巧妙的方法做2-3快速Ctrl- BreaksS IN一行,并得到所有正在运行的线程的2-3 threaddumps.只需查看所有线程"在哪里",就可以非常快速地找出性能问题所在.
这项技术可以在2分钟内揭示比我所知的任何其他技术更多的性能问题.
因为它有时会起作用,有时它会给你完全错误的答案.分析器在找到正确答案方面有更好的记录,而且通常可以更快地到达那里.
手动执行此操作实际上不能称为"快速"或"有效",但有几种分析工具可以自动执行此操作; 也称为统计分析.
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的精确指令和行号).有些程序只需要成千上万的样本进行有用的分析.
(当然,我们之前已经讨论过这个问题,但我认为这是一个总结辩论的好地方.)
程序员实际做的事情和他们推荐别人做的事情之间存在差异.
我知道有很多程序员(包括我自己)实际上使用这种方法.它只能帮助找到最明显的性能问题,但它快速而且肮脏且有效.
但我不会真的告诉其他程序员这样做,因为解释所有注意事项需要我太长时间.基于这种方法得出不准确的结论太容易了,并且在很多领域它根本不起作用.(例如,该方法不会显示由用户输入触发的任何代码).
就像在法庭上使用谎言探测器或"goto"声明一样,我们不建议您这样做,即使它们都有它们的用途.
我对双方的宗教基调感到惊讶.
分析很棒,当你可以做到时,它肯定会更加精致和精确.有时你不能,并且有一个可靠的备份是很好的.暂停技术就像你的电动工具距离太远或者餐馆用完时使用的手动螺丝刀.
这是一个简短的真实故事.一个应用程序(一种批处理任务)已经在生产中运行了六个月,突然之间运营商正在打电话给开发人员,因为它"太慢了".它们不会让我们在生产中附加采样分析器!您必须使用已安装的工具.在不停止生产过程的情况下,只需使用 Process Explorer(操作员已在机器上安装),我们就可以看到线程堆栈的快照.您可以浏览堆栈的顶部,使用回车键将其关闭,然后通过另一次鼠标单击获取另一个快照.您可以每隔一秒钟轻松获取样本.
不需要花很长时间才能看到堆栈的顶部是否经常出现在数据库客户端库DLL中(等待数据库),或者在另一个系统DLL中(等待系统操作),或实际上在某些方法中申请本身.在这种情况下,如果我没记错的话,我们很快就注意到应用程序在系统DLL文件调用中读取或写入网络文件的次数为8次.当然最近的"升级"改变了文件共享的性能特征.如果没有快速,肮脏和(系统管理员认可的)方法来查看应用程序在生产中所做的事情,我们将花费更多时间来测量问题,而不是纠正问题.
另一方面,当性能要求超出"足够好"以真正推动信封时,分析器变得至关重要,以便您可以尝试从所有紧密结合的前十或二十个热点中减少周期.即使您只是想在项目期间保持适度的性能要求,当您可以获得正确的工具来帮助您进行测量和测试,甚至将它们集成到您的自动化测试过程中时,它可以提供极大的帮助.
但是当电源耗尽(可以这么说)并且电池耗尽时,很清楚如何使用那把手动螺丝刀.
所以直接回答:知道你可以从停止程序中学到什么,但也不要害怕精密工具.最重要的是知道哪些工作需要哪些工具.
如果我们提出"为什么不能更好地了解它?"这个问题.那么答案就是主观的.据推测,为什么不能更好地了解它是因为分析提供了长期解决方案而不是当前的问题解决方案.它对多线程应用程序无效,对于花费大量时间渲染的游戏等应用程序无效.
此外,在单线程应用程序中,如果您有一个期望消耗最多运行时间的方法,并且您希望减少所有其他方法的运行时间,那么将更难确定哪些辅助方法可以集中精力一开始.
您的分析过程是一种可以接受且可行的方法,但分析为您提供了更多信息,并且可以向您显示更详细的性能改进和回归.
如果您有经过良好检测的代码,那么您可以检查的不仅仅是特定方法的时长; 你可以看到所有的方法.
通过分析:
然后,您可以在每次更改后重新运行方案,以确定性能改进/回归的程度.
您可以在不同的硬件配置上分析代码,以确定您的生产硬件是否足够.
您可以在负载和压力测试场景下分析代码,以确定信息量如何影响性能
您可以让初级开发人员更容易想象他们的更改对您的代码的影响,因为他们可以在您离开海滩或酒吧或两者时在六个月内重新分析代码.海滩酒吧,ftw.
分析更加重要,因为企业代码应该始终具有一定程度的分析,因为它给组织带来了长时间的好处.代码越重要,您的分析和测试就越多.
您的方法是有效的,另一个项目是开发人员的工具箱.它只是通过剖析而超过了它.
在"调试"模式下执行程序期间按下暂停按钮可能无法提供正确的数据来执行任何性能优化.说穿了,它是一种粗略的剖析形式.
如果您必须避免使用分析器,最好的办法是使用记录器,然后应用减速因子来"猜测"真正的问题所在.然而,Profilers是更好的猜测工具.
在调试模式下按下暂停按钮的原因可能无法给出应用程序行为的真实情况,因为调试器引入了可以减慢应用程序某些部分的额外可执行代码.可以参考Mike Stall的博客文章,了解调试环境中应用程序减速的可能原因.该帖子揭示了某些原因,例如断点太多,异常对象的创建,未经优化的代码等.关于未经优化的代码的部分很重要 - "调试"模式将导致大量优化(通常代码内嵌和重新被抛出窗口,启用调试主机(运行代码的过程)和IDE来同步代码执行.因此,在"调试"模式下重复执行暂停可能是一个坏主意.
采样分析器仅在以下情况下有用
您正在使用少量线程监视运行时.最好是一个.
每个线程的调用堆栈深度相对较小(以减少收集样本的难以置信的开销).
您只关心挂钟时间而不关心其他仪表或资源瓶颈.
您尚未检测代码以进行管理和监视(因此堆栈转储请求)
您错误地认为删除堆栈框架是一种有效的性能改进策略,无论固有成本(不包括被调用者)是否几乎为零
您不必费心学习如何在工作中日常应用软件性能工程
....
这些必须是您正在使用的一些简单示例,以便使用您的方法获得有用的结果.我无法想象一个项目,其中分析是有用的(通过任何方法),通过"快速有效"的方法可以获得不错的结果.启动和停止某些应用程序所需的时间已经使您的"快速"断言成为问题.
同样,对于非平凡的程序,您提倡的方法是无用的.
编辑:关于"为什么不是更好地知道"?
根据我的经验,代码审查避免了质量差的代码和算法,并且分析也会发现这些.如果你希望继续你的方法很棒 - 但我认为对于大多数专业人士来说,这是迄今为止尝试的事情清单,它永远不会得到积极的强化作为一个良好的时间利用.
对于小样本集来说似乎是非常不准确的,并且获得大样本集会花费大量时间用于其他有用的活动.
堆栈跟踪快照仅允许您查看应用程序的频闪X射线.您可能需要更多累积的知识,分析器可能会给您.
诀窍在于了解您的工具并选择最适合您手头的工作.
如果该程序正在生产中并由付费客户或同事同时使用该怎么办?分析器允许您在没有干扰的情况下进行观察(同样,因为根据海森堡原理它也会受到一点打击).
分析还可以为您提供更丰富,更详细的准确报告.从长远来看,这将更快.