我想知道如何写一个探查器?推荐哪些书籍和/或文章?有人可以帮我吗?
有人已经做过这样的事吗?
鼓励很多,不是我们:)
如果您只是试图合理地了解该计划在大部分时间内花费的时间,那么Profilers并不会太难.如果你对高准确性和最小的中断感到困扰,事情会变得困难.
因此,如果yoyu只想要一个分析器给你的答案,那就去找别人写的.如果你正在寻找智力挑战,为什么不去写一个呢?
我写了几个,因为这些年来已经变得无关紧要的运行时环境.
有两种方法
向每个函数或其他重要点添加内容以记录时间和位置.
定时关闭定时器并查看当前程序的位置.
JVMPI版本似乎是第一种 - uzhin提供的链接表明它可以报告很多事情(参见1.3节).执行此操作会发生什么变化,因此分析可能会影响性能(如果您正在分析什么是非常轻量级但通常称为函数,它可能会误导).
如果你可以得到一个定时器/中断告诉你程序计数器在中断时的位置,你可以使用符号表/调试信息来确定它当时所处的功能.这提供的信息较少,但破坏性较小.通过遍历调用堆栈以识别呼叫者等可以获得更多信息.我不知道这些甚至可能在Java中...
保罗.
我先看看那些开源项目:
Eclipse TPTP(http://www.eclipse.org/tptp/)
VisualVM(https://visualvm.dev.java.net/)
然后我会看看JVMTI(不是JVMPI)
http://java.sun.com/developer/technicalArticles/Programming/jvmti/
我写了一次,主要是为了让"深度采样"更加用户友好.手动执行此方法时,此处将对此进行说明.它是基于采样,而不是采取大量的小样本,你采取少量的大样本.
例如,它可以告诉你,指令I
(通常是一个函数调用)花费你总执行时间的百分比X,或多或少,因为它在X%的样本上出现在堆栈上.
想一想,因为这是一个关键点.只要程序正在运行,调用堆栈就存在.如果特定的调用指令I
在X%的时间内处于堆栈中,那么如果该指令可能消失,则X%的时间将消失.这不取决于I
执行的次数或函数调用的时间.因此,计时器和计数器都忽视了这一点.从某种意义上说,所有指令都是调用指令,即使它们只调用微码.
采样器的前提是,最好I
精确地知道指令的地址(因为这是你正在寻找的),而不是精确地知道数字X%.如果你知道你可以通过重新编码来节省大约30%的时间,那么你真的在乎你可能会减少5%吗?你仍然想要解决它.实际保存的时间量不会因你熟悉的X而变得更少或更多.
因此可以从定时器驱动样本,但坦率地说,我发现用户同时按下两个shift键来触发中断同样有用.由于20个样本通常很多,这样你可以确保在相关时间(即不等待用户输入时)采样,这是非常充分的.另一种方法是仅在用户按下两个shift键(或类似的东西)时执行定时器驱动的样本.
我并不关心采样可能会减慢程序的速度,因为目标不是测量速度,而是找到成本最高的指令.修好后,整体加速很容易测量.
分析器提供的主要功能是UI,因此您可以轻松地检查结果.抽样阶段的结果是调用堆栈样本的集合,其中每个样本是指令的地址列表,其中每个指令但最后一个是调用指令.用户界面主要是所谓的"蝴蝶视图".它具有当前的"焦点",这是一种特殊的指令.在左侧显示紧接该指令上方的调用指令,从堆栈样本中剔除.如果焦点指令是一个调用指令,则它下面的指令显示在右边,从样本中剔除.在焦点指令上显示百分比,即包含该指令的堆栈的百分比.类似地,对于左侧或右侧的每个指令,百分比按每个这样的指令的频率进行细分.当然,指令由文件,行号和它所在的函数名称表示.用户可以通过单击任何指令轻松浏览数据,使其成为新的焦点.
此UI的一个变体将蝴蝶视为二分,由函数调用指令的交替层和包含它们的函数组成.这可以让每个功能花费更多的时间.
也许它并不明显,所以值得一提的是这种技术的一些特性.
递归不是问题,因为如果一个指令在任何给定的堆栈样本上出现不止一次,那么仍然只计算一个包含它的样本.仍然可以确定的是,通过删除它所节省的估计时间是它所在的堆栈百分比.
请注意,这与调用树不同.无论调用树的分支有多少,它都会为您提供指令的成本.
UI的性能不是问题,因为样本的数量不需要非常大.如果特定指令I是焦点,则很容易找到样本如何包含它,并且对于每个相邻指令,包含I的样本中有多少还包含旁边的相邻指令.
如前所述,采样速度不是问题,因为我们没有测量性能,我们正在诊断.抽样不会对结果产生偏差,因为抽样不会影响整个计划的作用.即使N指令完成任何次数,也需要N个指令完成的算法仍然需要N个指令.
我经常被问到如何对以毫秒为单位完成的程序进行采样.简单的答案是将它包装在外部循环中,以使其花费足够长的时间来进行采样.您可以找出X%的时间,删除它,获得X%加速,然后删除外部循环.
我称之为YAPA(又一个性能分析器)的这个小小的分析器是基于DOS的,并且做了一个很好的小演示,但是当我有认真的工作要做时,我会回到手动方法上.这样做的主要原因是单独的调用堆栈通常不足以告诉您为什么要花费特定周期的状态信息.您可能还需要了解其他状态信息,以便更全面地了解当时程序正在执行的操作.由于我发现手动方法非常令人满意,我搁置了工具.
在谈论分析时经常遗漏的一点是,您可以反复进行以找到多个问题.例如,假设指令I1
在5%的时间内I2
处于堆栈中,并且在50%的时间内处于堆栈中.很容易找到20个样本I2
,但可能不会I1
.所以你解决了I2
.然后你再做一遍,但现在I1
需要10%的时间,所以20个样本可能会看到它.这种放大效果允许重复应用轮廓分析以实现大的复合加速因子.