在這個問題中,我想問一下關於如何測試Java代碼性能的知識。通常的方法沿着這些線路的工作原理:有效的性能測量
long start = System.nanoTime();
for(int i=0; i<SOME_VERY_LARGE_NUMBER; i++) {
...do something...
}
long duration = System.nanoTime() - start;
System.out.println("Performance: "
+ new BigDecimal(duration).divide(
new BigDecimal(SOME_VERY_LARGE_NUMBER, 3, RoundingMode.HALF_UP)));
「優化」版本的移動呼叫System.nanoTime()
進入死循環,因爲System.nanoTime()
增長的誤差需要更長的時間(和方式難以預料在運行時的行爲)比i ++
和比較。
我的批評是:
這給了我的平均運行時間,但這個值取決於一個因素,我並不真正感興趣的:如系統負載,同時測試迴路正在運行或跳躍時,JIT/GC踢。
在大多數情況下這種方法不會(好多)更好嗎?
- 運行代碼來衡量往往不夠給力JIT編譯
- 運行在一個循環的代碼和測量的執行時間。記住最小值並在此值穩定時中止循環。
我的理由是我通常想知道某些代碼可以有多快(下界)。由於外部事件(鼠標移動,顯卡中斷,因爲桌面上有模擬時鐘,交換網絡數據包......),任何代碼都可能變得任意慢,但大多數情況下,我只想知道速度有多快我的代碼可以在完美的情況下。因爲我不必在幾秒鐘或幾分鐘內運行代碼(以消除不需要的效果),它還會使性能測量速度快得多。
有人可以確認/揭穿這個?
我經常做類似的事情,但手動。我多次重複測試,並以最低的數字進行測試。我有和你一樣的推理。當然,如果您的替代解決方案在GC的壓力數量上有所不同,那麼不應該考慮這個因素。 –
爲什麼「優化」版本將*調入*循環?沒有編譯器會這樣做。 –
@IraBaxter:我的意思是人類「優化」以獲得更好的「精確」(因爲新的測量不會計算循環)。但像往常一樣,這裏的直覺是錯誤的。 –