4

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

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

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

此外,所有这些的源代码都可以在此处获得。在“src”文件夹下查看。

4

1 回答 1

3

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

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

即时编译的效果是启动时间大大减少(整个应用程序在运行之前不需要编译)而且关键部分运行得尽可能快(因为它们最终被编译) . 看起来关键部分是在第一次评估中的某个地方编译的。

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

如果您将您的标记swap为 as final,它将使编译器能够内联对此方法的调用。由于此方法很小且经常被调用,因此内联它(这是即时编译的一部分)将显着提高性能。

为了提供一致的测试环境,您可以在运行测试时禁用即时编译。

于 2012-11-28T06:45:52.963 回答