2012-08-30 57 views
0

我想比較的數據類型「詮釋」和「長」的表現,當運行到這個奇怪的問題,不同的結果,基本上我有兩個單元測試:相同的測試獲得與JDK6和JDK7

@Test 
public void testLongOperationPerformance(){ 
    StopWatch sw = new StopWatch(); 
    sw.start(); 
    long count = 0l; 
    for(int i = 0; i < Integer.MAX_VALUE; i ++){ 
     count++; 
    } 
    sw.stop(); 
    System.out.println(count); 
    System.out.println(sw.elaspedTimeInMilliSeconds()); 
} 

@Test 
public void testIntegerOperationPerformance(){ 
    StopWatch sw = new StopWatch(); 
    sw.start(); 
    int count = 0; 
    for(int i = 0; i < Integer.MAX_VALUE; i ++){ 
     count++; 
    } 
    sw.stop(); 
    System.out.println(count); 
    System.out.println(sw.elaspedTimeInMilliSeconds()); 
} 

這兩個單元測試是做同樣的事情,區別在於使用int作爲計數器的數據類型,另一個使用long。 結果:

jdk6u32 (64 bit): 
test with long 
2147483635 
96 
test with int 
2147483647 
2 

jdk7 (64 bit) 
test with long 
2147483647 
1599 
test with int 
2147483647 
1632 

我注意到:

    在jdk6u32
  1. ,與詮釋測試比測試快得多與jdk6u32長
  2. ,測試結果與int和測試與測試之間的不同長
  3. 在jdk7中,兩個測試都差不多都很快,它們都比jdk6u32慢很多
  4. 在jdk7中,兩個測試都得到了相同的結果

任何人都可以解釋爲什麼它是這樣嗎?

+0

你是說jdk6u32返回錯誤的數字(缺少12次迭代)? – Thilo

+0

您確定要發佈的代碼和結果:看起來很奇怪,使用JDK,漫長的測試正在吸取循環的一部分。 – Matteo

+0

你也應該選擇不那麼微不足道的測試。編譯器或JIT可以優化您的代碼,並且可以輕鬆地一次性刪除循環,因爲可以輕鬆計算最終計數的值。 – Matteo

回答

6

Java JIT特別擅長消除無所作爲的代碼。在你的榜樣,環

long count = 0l; 
for(int i = 0; i < Integer.MAX_VALUE; i ++){ 
    count++; 
} 

可以

long count = 0l; 
count += Integer.MAX_VALUE * 1; 

更換你所時機是需要多長時間來檢測和刪除的循環。這一次可以取決於它之前做了什麼,所以我建議以不同的順序測試循環,看看是否會改變結果。

在Java 6 & 7中,一些循環優化被錯誤地優化了。

例如這個無限循環並不總是無限對有些更新

for(int i=0; i < Integer.MAX_VALUE; i += 2) 

出於這個原因,一些更新有不同的優化或關閉,這取決於它們是否有效,該版本。我建議嘗試最新版本的Java 7以查看它是否有所作爲。

+0

謝謝彼得。我沒有得到的是,如果JDK6對測試代碼做了優化,爲什麼jdk7沒有。 – seiya

+0

另外,即使JIT執行了代碼替換,結果也不應該變得不對,對吧? jdk6和long類型的結果甚至不正確。 – seiya

相關問題