2013-06-03 94 views
1

的時間我有這樣的代碼:爪哇 - 執行

public static void main(String[] args) { 

    long f = System.nanoTime(); 

    int a = 10 + 10; 

    long s =System.nanoTime(); 

    System.out.println(s - f); 

    long g = System.nanoTime(); 

    int b = 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10; 

    long h =System.nanoTime(); 

    System.out.println(h - g); 

} 

有了這個輸出/秒:
測試1:

427 
300 

測試2:

533 
300 

測試3:

431 
398 

根據我的測試場景,爲什麼行int b = 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10 + 10;執行速度比int a = 10 + 10;更快?

+0

在主方法中的_one_運行結束這是太不確定。至少在一個循環內運行幾百萬次。 – NilsH

+0

Micheal 請在下面檢查URL。 Java中Integer類型的到期池行爲會導致後者運行得更快,因爲整數b執行的時間10已經在池中。希望這可以幫助。 http://stackoverflow.com/questions/13098143/java-integer-constant-pool –

+0

我每次運行這段代碼都會得到不同的結果,從0到600,有時其中一個是0。這些操作太快,您無法一次測試。 – Djon

回答

5

Microbenchmarks非常難以正確使用,特別是在諸如Java的「智能」語言中,編譯器和Hotspot可以進行大量優化。你幾乎肯定沒有測試你認爲你正在測試的東西。請閱讀Anatomy of a Flawed Microbenchmark瞭解更多詳細信息和示例(現在這是一篇相當古老的文章,但其原理與以往一樣有效)。

在這種特殊情況下,我可以看到了蝙蝠的權利至少有三個問題:

  • 的代碼不會在所有執行任何另外,因爲編譯器將分配變量的編譯時常數值。 (即,就好像你的代碼被讀取爲int a = 20;int b = 120;
  • 在大多數系統上,nanoTime的粒度相當高。這與操作系統的負載相結合,意味着您的測量實驗誤差遠大於結果本身的大小。
  • 即使增加發生,你還沒有「熱身」虛擬機;通常無論你放在第二位的操作會因爲這個原因而顯得更快。

潛在的潛在危害也可能存在。

故事的寓意是在真實世界的條件下測試你的代碼,看它的行爲如何。絕不能單獨測試小塊代碼,並假設整體性能是這些塊的總和。

+0

這一個清理我的路徑。我的意思是,所有的答案都有相同的觀點。但是這篇文章闡述了我做錯了什麼。 –

4

首先是。 Java編譯器進行常量表達式的優化,使您在編譯時的代碼將被轉換爲:

int b = 120; 

至於結果JVM執行分配給a=20b=120同時附近。

第二個。你對大系統進行簡短的測量(我的意思是整個計算機,包括操作系統,交換過程,另一個運行過程......)。所以你可以在很短的時間內得到隨機系統的快照。這就是爲什麼你不能推斷真假,a分配比b更快。爲了證明這一點,你必須將代碼測量放在相當大的循環中 - 大致執行1,000,000次。如此大的重複可讓您順利進行期望(在數學意義上的這個詞)

+2

這可以通過檢查生成的字節碼('bipush 20'和'bipush 120')來確認。 – assylias

+1

大系統還包括JVM本身 – LeGEC

2

這不是衡量表現的正確方法。

首先,不要測量這麼小的一段代碼。 而是像@NilsH所建議的那樣撥打數百萬次, 並通過將已用時間除以通話次數獲得平均時間。其次,JVM可能對您的代碼 執行優化,因此您需要給它一個「預熱」時間。 在開始測量之前,不需要測量任何時間就可以讓幾百萬的「乾燥」運行。