我想知道如何写一个探查器?推荐哪些书籍和/或文章?有人可以帮帮我吗?
有人已经做过这样的事吗?
答案 0 :(得分:11)
鼓励很多,不是我们:)
如果您只是试图合理地了解该计划在大部分时间内花费的时间,那么分析师并不会太难。如果你对高准确性和最小的干扰感到困扰,事情会变得困难。
因此,如果yoyu只想要一个分析器会给你的答案,那就去别人写的。如果你正在寻找智力挑战,为什么不去写一个呢?
我写了一对,因为这些年来已经变得无关紧要的运行时环境。
有两种方法
为每个功能或其他重要点添加内容,记录时间和位置。
定时关闭计时器并查看程序当前所在的位置。
JVMPI版本似乎是第一种 - uzhin提供的链接表明它可以报告很多事情(参见1.3节)。执行此操作会发生什么变化,因此分析可能会影响性能(如果您正在分析什么是非常轻量级但通常称为函数,它可能会误导)。
如果你可以得到一个定时器/中断告诉你中断时程序计数器的位置,你可以使用符号表/调试信息来确定它当时所处的功能。这提供的信息较少,但破坏性较小。通过遍历调用堆栈以识别呼叫者等可以获得更多信息。我不知道这些甚至可能在Java中...
保罗。
答案 1 :(得分:8)
我会首先看一下这些开源项目:
然后我会看看JVMTI(不是JVMPI)
答案 2 :(得分:8)
答案 3 :(得分:2)
JVMPI规范:http://java.sun.com/j2se/1.5.0/docs/guide/jvmpi/jvmpi.html
我向你的勇气和勇敢致敬
编辑:正如用户Boune所说,JVMTI: http://java.sun.com/developer/technicalArticles/Programming/jvmti/
答案 4 :(得分:0)
作为另一个答案,我只是在sourceforge上看了LukeStackwalker。它是一个很好的小型堆栈采样器示例,如果你想编写一个探查器,这是一个很好的起点。
在我看来,这是正确的做法:
它应该保留原始堆栈样本。实际上,它在样本时总结了功能级别。这会丢失定位有问题的呼叫站点的关键行号信息。
如果要存放它们是一个问题,它不需要采取这么多样本。由于典型的性能问题成本从10%到90%,因此20-40个样品将非常可靠地显示出来。数百个样本提供更高的测量精度,但它们不会增加定位问题的可能性。
用户界面应根据陈述而非功能进行总结。如果保留原始样品,这很容易做到。附加到声明的关键措施是包含它的样本的分数。例如:
5/20 MyFile.cpp:326 for(i = 0; i< strlen(s); ++ i)
这表示在调用strlen
的过程中,MyFile.cpp中的第326行出现在20个样本中的5个中。这非常重要,因为您可以立即看到问题,并且您知道修复它可以获得多少加速。如果您将strlen(s)
替换为s[i]
,它将不再花费时间在该通话中,因此这些样本将不会发生,并且加速将大约为1 /(1-5 / 20)= 20 /(20-5)= 4/3 = 33%加速。 (感谢David Thornley提供此示例代码。)
UI应该有一个显示语句的“蝴蝶”视图。 (如果它也显示了函数,那没关系,但语句才是真正重要的。)例如:
3/20 MyFile.cpp:502 MyFunction(myArgs)
2/20 HisFile.cpp:113 MyFunction(hisArgs)
5/20 MyFile.cpp:326 for(i = 0; i< strlen(s); ++ i)
5/20 strlen.asm:23 ...一些汇编代码......
在此示例中,包含for
语句的行是“关注焦点”。它发生在5个样本上。上面的两行表示,在其中3个样本中,它是从MyFile.cpp:502
调用的,而在其中2个样本中,它是从HisFile.cpp:113
调用的。它下面的一行表示,在所有5个样本中,它都在strlen
(毫不奇怪)。通常,焦点线将具有“父母”树和“儿童”树。如果由于某种原因,焦点线不是你可以修复的东西,你可以上下移动。目标是找到尽可能多的样本可以修复的行。
重要提示:不应将分析视为一次。例如,在上面的示例中,我们通过修复一行代码获得了4/3的加速。当重复该过程时,其他有问题的代码行应该以他们之前执行的频率的4/3显示,因此更容易找到。我从来没有听说有人在讨论迭代分析过程,但是获得整体大型复合加速是至关重要的。
P.S。如果在单个样本中多次出现语句,则表示存在递归。这不成问题。它仍然只计为包含该语句的一个样本。情况仍然是声明的成本用含有它的样本的分数来近似。