多年前,我建立了一个性能分析器,并在回答其他问题时在SO上描述了它,但我现在无法找到该问题。这个分析器基于我使用数十年的技术,其中
这里提供了一个示例。它基于堆栈采样,关键在于如何呈现信息以及用户的思考过程。
我认为需要质疑并加强学校(由于教授们很少接触实际软件)所教授的有关性能调优的一般信念,并继续通过50,000程序员不会错的现象。从巡游SO中您可能会发现,我远非孤单。
我认为性能分析技术正在逐渐发展(在我看来是更好的方向),朝着堆栈采样和探索结果的方式发展。以下是我依赖的见解(您可能会感到有些不适):
揭示性能问题以便修复和测量性能是两个完全不同的任务。它们是手段和目的,不应混淆。
要揭示性能问题,需要找到哪些活动占用了大量挂钟时间,并且可以用更快的东西替换。
这些活动的好处在于,它们需要时间的事实使它们暴露于程序状态的随机时间样本中。
如果在您关心的时间间隔内进行采样,则不需要太多的样本。即,等待用户输入时没有取样的意义。为此,在我的分析器中,我让用户使用键触发样本。
您不需要太多的样本的原因是这样的。任何给定的性能问题都会在感兴趣的时间间隔内占用一些挂钟时间的X分数。在该间隔内进行的随机抽样具有“捕捉它在行动中”的X概率,因此如果采取N个样本,则预期在行动中捕捉到的样本数量为NX。该样本数量的标准差为sqrt(NX(1-X))。例如,如果N = 20,X = 20%,则可以预计大约有2到6个样本显示问题。这为您提供了一个不精确的问题度量,但它确实告诉您值得修复,并且它为您提供了一个非常精确的位置,无需进一步的侦探工作。
问题通常表现为比必要的更多的函数、过程或方法调用,特别是随着软件变得越来越大,有更多的抽象层和因此有更多的堆栈层。我首先查找的是出现在多个堆栈样本中的调用站点(而不是函数,而是调用语句或指令)。它们出现在的堆栈样本越多,花费就越高。我查找的第二件事是“它们可以被替换吗?”如果它们绝对不能被更快的东西替换,那么它们就是必要的,我需要寻找其他地方。但是,它们经常可以被替换,并且我获得了很好的加速。因此,我仔细查看特定的堆栈样本,而不是将它们聚合成测量结果。
递归不是问题,因为指令成本的原则是它在堆栈上的时间百分比相同,即使它调用自身。
这不是我一次做的事情,而是在连续的传递中进行的。我修复的每个问题都会使程序花费更少的时间。这意味着其他问题成为时间的更大分数,使它们更容易找到。这种效果会累积,因此通常可以实现戏剧性的累积性能改进。
我还可以继续下去,但我祝你好运,因为我认为需要更好的分析工具,而您有很好的机会。