2014-03-06 44 views
1

我測試的分支預測,這樣的代碼:爲什麼JVM不執行代碼?

//first loop 
int sortedSum = 0; 
long sortedStartTime = System.nanoTime(); 
for (int i = 0; i < sortedArray.length; i++) { 
    if (sortedArray[i] < 0) { 
     sortedSum += sortedArray[i]; 
    } 
} 
long sortedTime = System.nanoTime() - sortedStartTime; 

//second loop 
int randomSum = 0; 
long randomStartTime = System.nanoTime(); 
for (int i = 0; i < randomArray.length; i++) { 
    if (randomArray[i] < 0) { 
     randomSum += randomArray[i]; 
    } 
} 
long randomTime = System.nanoTime() - randomStartTime; 

System.out.println("random time: " + randomTime); 
System.out.println("sorted time: " + sortedTime); 

很簡單打印有關每個for循環的時間。

請注意,sortedSumrandomSum在循環中分配但從未被訪問。

這裏我們不談論分支預測,而是輸出結果。 的輸出是:

random time: 32 
sorted time: 1595942 

然後,我把第二個for循環的第一(第一randomArray環路,第二sortedArray)之前。 輸出是:

random time: 1541919 
sorted time: 40 

看來JVM不執行第二循環。我反編譯類文件,反編譯器不會擦除任何東西。

爲什麼?爲什麼JVM執行第一個循環?

P.S. 環境是:

Ubuntu 12.04 LTS 
java version "1.7.0_11" 
Java(TM) SE Runtime Environment (build 1.7.0_11-b21) 
Java HotSpot(TM) 64-Bit Server VM (build 23.6-b04, mixed mode) 
+0

在您的第一個循環中,JVM正在升溫。在測量另外兩個之前,先製作第三個循環來預熱JVM。 – Ingo

+0

http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java – kiheru

+0

由於JVM實際上正在執行兩個循環,所以問題主題是錯誤的。這是時間問題。 –

回答

2

當在運行代碼足夠它觸發整個方法進行優化(在背景中)

這意味着如果有一個循環它不它迭代10K倍和做任何事情,你實際上計時需要多長時間來檢測循環沒有做任何事情,並取而代之。

在第二個循環的情況下,無論哪種情況,該方法都已被優化。

我建議你有一個外部循環運行這個測試3次,你應該明白我的意思。

它可以放棄循環的原因是;

  • ,你不使用計算出的值,所以calculateSum能夠被丟棄
  • 則不需要數組訪問
  • 則循環本身並不需要。
+0

是的,多次運行測試(比如將代碼放在函數中調用) –

+0

@PaulVerest從頭幾次運行測試,不像循環運行多次。對於性能來說,它可能會非常不同。 –

0

這樣的:

我們在這裏談論的即時編譯。編譯器在開始執行後只會優化一段時間。我猜他會優化一切。只要JIT編譯器尚未啓動,就會執行第一個循環。

+0

爲什麼你覺得即時編譯是獨立的線程? –

+0

是什麼讓你覺得我認爲它是在一個獨立的線程? – kutschkem

0

我認爲這無關與Java,但CPU,內存和緩存:

起初System.nanoTime()應用程序在內存中,在CPU緩存級別1(在CPU的速度)執行代碼。當程序開始執行時,CPU將開始將內存塊的前面 提前到1或2級,所以順序讀/寫會增加速度。

嘗試使用比CPU級別3高速緩存大得多的數組,例如, 10MB和隨機索引,即按隨機順序準備索引數組。這將消除CPU兌現效應。