JVM中这些时序问题的原因是什么?

时间:2012-11-28 06:11:21

标签: java algorithm sorting jvm timing

我一直在摆弄一些排序算法并对它们进行计时,看看它们的效果如何。为此,我创建了一个包含许多整数排序算法的静态类,以及另一个用于计时和将数据导出到csv的类。

我开始查看上述数据,我注意到了一个有趣的趋势。我的程序创建了5个不同的随机数组进行测试,每个排序算法在每个数组上平均需要10次不同的试验。奇怪的是,第一个阵列似乎有一些算法的平均时间明显更长,但其他算法则没有。以下是备份它的一些示例数据: Dataset 1Dataset 2Dataset 3(时间以纳秒为单位)。

我不确定它是否与某些算法,我实现算法的方式,JVM或其他一些因素组合有关。有人知道这种类型的数据是如何发生的吗?

此外,所有这些的源代码都可用here。查看'src'文件夹下的内容。

1 个答案:

答案 0 :(得分:3)

这看起来像是即时编译的效果。

为减少启动时间,首次运行代码时,将直接从字节代码中解释代码。只有在任何特定代码段运行多次之后,JIT才会确定它是一个关键部分,并且值得重新编译为本机代码。然后它以编译的形式替换该方法。

即时编译的影响是启动时间大大减少(整个应用程序在运行之前不需要编译),但关键部分也尽可能快地运行(因为它们最终编译)。看起来关键部分是在第一次评估中编写的。

我不确定为什么某些算法没有表现出编译的速度。最有可能的原因是它们与其他先前的算法共享其关键部分。例如,Insertion排序很大程度上依赖于在选择排序评估期间编译的swap方法。另一个可能的原因在于注意到一致运行的mergeSort并不严重依赖于函数调用,因此它不会受益于内联。另一方面,堆排序在很大程度上依赖于siftDown方法,编译器可能难以内联。

如果您将swap标记为final,则会使编译器内联对此方法的调用。由于这种方法很小而且经常被调用,所以内联它(它是及时编译的一部分)将有助于提高性能。

为了提供一致的测试环境,您可以在运行测试时disable just-in-time compilation