作为学校练习的一部分,我想将排序算法作为Java练习进行比较和对比。
我自己实现了排序算法,并对实现Person
接口的类Comparable
的对象进行了排序。
到目前为止一直很好,但我无法解释的是为什么在第一次调用我的排序方法时,排序需要的时间比后续调用要长? 输出波纹表示我的结果 Best,Worst和Avg指的是传递给排序方法的未排序数组:
这是我的输出:
1-call of the sorting methods
InsertionSort Best:1799ms Worst:78ms Avg:789ms
MergeSort Best:10ms Worst:3ms Avg:5ms
2-call of the sorting methods
InsertionSort Best:1065ms Worst:39ms Avg:691ms
MergeSort Best:3ms Worst:2ms Avg:5ms
3-call of the sorting methods
InsertionSort Best:1066ms Worst:39ms Avg:692ms
MergeSort Best:3ms Worst:2ms Avg:5ms
4-call of the sorting methods
InsertionSort Best:1065ms Worst:39ms Avg:691ms
MergeSort Best:3ms Worst:2ms Avg:5ms
JVM是否对后续调用进行了任何优化? 我很困惑,非常感谢任何帮助!
编辑:感谢您的建议和答案到目前为止! 要明确几点 - 我的输出中的每个调用都指的是完成排序所需的时间! 每次排序后,我再次使用UNSORTED数组进行新的调用!
我的源代码可以作为zip文件下载为eclipse项目,位于以下Dropbox链接: dropbox link to eclipse project.zip
P.S。我没有使用剖析器的经验 - 如果你能指点我一个教程,那就太好了。
答案 0 :(得分:8)
这里有许多工作,因为各种反应都表明了这一点。
但是第一次运行的长运行时间可能是由JIT(即时)编译解释的。作为discussed here,您的算法将作为解释的字节码在JVM中运行一段时间。当Hotspot监视器确定您的sort循环成本很高时,JVM会将它们编译为本机代码。在那之后,他们会跑得快得多。第一次运行的缺点是在解释器中运行一段时间加上编译的额外成本。这就是"warming up" is a common term in Java benchmarks的原因。
不同输入的性能差异与排序算法有关。许多算法在初始数据组织的基础上表现不同,并且许多算法被有意组织以在最初排序或接近排序的数据上表现良好。 Here is a brilliant demonstration for the case of nearly sorted input。例如。插入排序一般是二次时间,但在近似排序的输入上是线性时间(实际上是O((k + 1)n),对于大小为n的输入,其中元素不超过正确排序的k个位置。)
然后链接已经引用了分支预测问题。现代处理器有各种机制,试图猜测"哪种方式分支(基本上是"在机器级别的#34;语句)将基于程序运行时收集的最近历史记录。猜测的成本很高。猜测的好坏可能会受到算法和数据细节的影响。
答案 1 :(得分:6)
由于Branch Prediction,处理已排序的数组比处理未排序的数组更快 the most famous Stack Overflow question已涵盖广泛。