2012-11-28 56 views
4

我一直在擺弄一些排序算法,並計時看它們是多麼有效。爲此,我創建了一個靜態類,其中包含許多用於整數的排序算法,另一類用於對它們進行計時並將數據導出到csv。JVM中這些計時問題的原因是什麼?

我已經開始查看上述數據,並且我注意到了一個有趣的趨勢。我的程序創建了5個不同的隨機數組進行測試,每個排序算法對每個數組進行10次不同試驗的平均值。奇怪的是,第一個數組似乎有一些算法的平均時間顯着更長,但其他算法則沒有。這裏有一些示例數據來備份它: Dataset 1,Dataset 2Dataset 3(時間以納秒爲單位)。

我不確定它是否與某些算法,我實現算法,JVM或其他因素組合有關。有人知道這種數據是如何發生的嗎?

此外,所有的源代碼可用here。在'src'文件夾下查找。

+0

結果** [統計顯着性](http://en.wikipedia.org/wiki/Statistical_significance)**?你有多少次運行你的實驗?您是否使用[統計假設檢驗](http://en.wikipedia.org/wiki/Statistical_hypothesis_testing)提取[P-Value](http://en.wikipedia.org/wiki/P-value)? – amit

+2

熱身時間在JVM中很常見;在試圖計算時間之前,大多數基準測試都會運行代碼很長一段時間,直到性能穩定。這給了JVM加載所有類,配置文件,編譯熱點等的機會。我不知道爲什麼某些測試的熱身不同於其他測試,但是您可能想要嘗試更改排序的順序並看看這是否有所作爲。 – rici

+0

@rici我想知道旁邊的熱點有什麼可以在這裏產生效果。整個源代碼都在一個類中。 –

回答

3

這看起來像是即時編譯的效果。

爲了減少啓動時間,當代碼第一次運行時,它直接從字節代碼解釋。只有在多次運行特定代碼之後,JIT纔會決定它是一個關鍵部分,值得重新編譯爲本機代碼。然後用它的編譯形式替換該方法。

即時編譯的影響是啓動時間極其縮短(整個應用程序不需要在運行之前編譯),而且關鍵部分的運行速度也儘可能快(因爲它們最終被編譯)。看起來關鍵部分在第一次評估中被編譯。

我不確定爲什麼有些算法沒有表現出編譯加速。最有可能是因爲他們與其他一些以前的算法共享他們的關鍵部分。例如,插入排序嚴重依賴於在選擇排序評估期間編譯的swap方法。另一個可能的原因在於注意mergeSort一貫運行,並不嚴重依賴函數調用,所以它不會從內聯中受益。另一方面,堆排序很大程度上依賴於siftDown方法,這對於編譯器來說可能很困難。

如果您將swap標記爲final,它將使編譯器能夠調用此方法。由於這個方法很小並且經常被調用,因此內聯(這是剛剛編譯的一部分)將顯着地幫助性能。

爲了提供一致的測試環境,您可以在運行測試時使用disable just-in-time compilation

+0

嘗試標記'交換'爲最終,但沒有奏效。然後,我使用鏈接中的命令行開關禁用JIT編譯,現在數據看起來更加[統一](https://dl.dropbox.com/u/24472738/JIT%20off.png)。謝謝! – brenns10

相關問題