Java代码执行的字节码计数的最佳方法是什么?

4

我试图获取各种Java程序的时间数据,然后根据此时间数据执行一些回归分析。以下是我用于获取时序数据的两种方法:

  • System.currentTimeMillis():我最初使用了这种方法,但我希望当多次运行同一程序时,时间数据保持不变。在这种情况下,变化很大。当两个相同代码的实例并行执行时,变化更大。因此,我放弃了这个方法,开始寻找一些性能分析工具。
  • Hotspot JVM中的-XX countBytecodes标志:由于时间数据的变化很大,我想测量执行此代码时执行的字节码数量。当多次执行同一程序时,这应该会给出更静态的计数。但是这也有变化。当程序按顺序执行时,变化很小,但在执行相同代码的 parellel 运行期间,变化很大。我还尝试使用-Xint进行编译,但结果类似。

因此,我正在寻找一些性能分析工具,它可以在执行代码时提供执行的字节码计数。当同一程序运行时,计数应保持恒定(或相关性接近1)。或者,如果可以基于其他指标获得时间数据,那么应在多次运行时保持几乎不变。


我不知道。你为什么要这样做?VisualVM是一个不错的分析工具。但是在JIT优化方法后,你试图收集的数据就没有意义了,所以我不知道你如何收集你的数据。 - Elliott Frisch
@ElliottFrisch 我想根据执行时间性能对代码进行评分,并将程序相互比较,基于具有类似性能的程序对数据进行聚类等。 - aichemzee
你为什么想要排除特定时间变化对于你的测量结果的影响?这样做不会削弱它们的意义吗? - Drux
@ElliottFrisch 我正在使用 -Xint 标志,它强制 JVM 在解释模式下执行所有字节码。因此,这些优化位不应该出现。结果应该可以正常工作,对吗? - aichemzee
@Drux 我并不排除这个事实,我只是确保两个完全相同的代码在执行时给出相同的时间数据。 - aichemzee
显示剩余2条评论
1个回答

4
当同一个程序运行多次时,我希望时间数据能保持恒定。除非您的机器专为硬实时系统设计,否则在真实机器上是不可能实现的。
我正在寻找一些分析器,可以在执行代码时给出执行的字节码计数。
即使您能做到这一点,也无法证明任何事情。例如,您将无法看到“++”比“%”便宜90倍,具体取决于您运行的硬件。您将无法看到if的分支失误比推测性分支昂贵多达100倍。您将无法看到访问触发TLB失误的内存区域的内存访问可能比复制4 KB的数据更昂贵。
如果有其他基于度量标准的方法可以获取时间数据,并且应该在多次运行中保持几乎恒定。您可以多次运行并取平均值。这将隐藏任何高结果/异常值,并为您提供有利的吞吐量概念。如果足够长时间运行,则可以成为给定机器的可重复数字。

我明白这不是情况,而且变化很大就像我说的一样。所以我将度量从执行时间改为执行的字节码数量。它们应该与时间数据有直接关系,并且在多次运行相同程序时几乎应该是恒定的。 - aichemzee
@aichemzee 的问题是,即使您获得了可重现的字节码字节数,它也不能告诉您应用程序的性能或定时情况,例如 Thread.sleep(100000);System.gc(); 中有多少字节。 - Peter Lawrey
1
是的,它不会。但我根据代码在输入大小变化时的可扩展性进行评分。因此,这样的语句要么对常数项做出贡献,要么改变时间函数的系数,而不是时间函数本身。(例如t(N)的时间函数= C_1 * N + C_2,因此C_1和C_2将受到影响,预测的时间函数仍将显示线性缩放) - aichemzee
是的,最多会减慢10倍。如果执行次数在10次后仍不稳定呢? :) (让我先运行实验以获得更好的数字)。 - aichemzee
@PeterLawrey:“在真实的机器上不可能做到这一点”——当然可以。使用简单的代码,如void inc() { counter++; },执行的字节码数量始终为7(aload,dup,getfield,iconst_1,iadd,putfield,return)。计算这些确实对于测量时间复杂度非常有用。这需要时间,不适用于生产环境中的代码测量,但是MMIX甚至模拟了机器指令的时间。 - Roland Illig
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接