2013-06-12 42 views
0

所有的圈數預計大概都是同一時間,那麼爲什麼第一圈和第二圈會出現異常?納秒級定時器給出奇數結果

輸出:

6.695178 ms : Lap #0 
18.698311 ms : Lap #1 
0.143568 ms : Lap #2 
0.043931 ms : Lap #3 
0.061594 ms : Lap #4 
0.038496 ms : Lap #5 
0.038043 ms : Lap #6 
0.043478 ms : Lap #7 
0.038949 ms : Lap #8 
0.061141 ms : Lap #9 

SSCCE:

import java.util.LinkedList; 

public class StopwatchSSCCE { 

    public static void main(String [] args){ 
     // ten laps of 2 billion iterations each 
     int laps = 10; 
     int iterationsEach = 2000000000; 

     Stopwatch stopwatch = new Stopwatch(); 

     for(int lap = 0; lap < laps; lap++){ 
      // empty loop 
      for(int i = 0; i < iterationsEach; i++); 

      // add lap 
      stopwatch.lap("Lap #" + lap); 
     } 

     stopwatch.printLaps(); 
    } 

    private static class Stopwatch { 

     private long startTime, lastLap; 

     private LinkedList<String> laps = new LinkedList<>(); 

     public Stopwatch(){ 
      reset(); 
     } 

     public void clearLaps(){ 
      laps.clear(); 
     } 

     public void reset(){ 
      startTime = lastLap = System.nanoTime(); 
     } 

     public long timeSinceLastLap(){ 
      return System.nanoTime() - lastLap; 
     } 

     public void lap(String title) { 
      double split = timeSinceLastLap()/1000000.0; 
      lastLap = System.nanoTime(); 
      laps.add(split + " ms :\t" + title); 
     } 

     public void printLaps(){ 
      for(String lap : laps) System.out.println(lap); 
     } 
    } 
} 
+2

他們永遠不會平等。 SO調度程序可能正在運行。該程序不能獨佔訪問處理器。 – acdcjunior

+0

當然,如果第一圈是異常值。但爲什麼第二更是如此?這可能會使他們平均,但這意味着這個班級是有缺陷的,因爲每次都需要加熱。 – rtheunissen

+2

「*所有圈數預計大約在同一時間*」=>否 – assylias

回答

6

以下是一些可能導致錯誤的原因。

main方法將由JIT幾倍運行過程中編譯

如果使用-XX:+PrintCompilation標誌,你會得到這樣的輸出:

86 1 %   javaapplication4.Test1::main @ 26 (73 bytes) 
90 1 %   javaapplication4.Test1::main @ -2 (73 bytes) made not entrant 
91 2 %   javaapplication4.Test1::main @ 26 (73 bytes) 
4.090457 ms : Lap #0 
6.412305 ms : Lap #1 
0.040696 ms : Lap #2 

所以前幾運行顯然影響由彙編。

JVM在啓動時有一些「內容」,這也會影響前幾次運行。

基本閱讀:How do I write a correct micro-benchmark in Java?

+0

這是我以後的答案 - 謝謝。 – rtheunissen

+0

@ paranoid-android另外請注意,經過幾次編譯後,整個內部循環可能會被優化掉,因爲它沒有任何副作用。 – assylias

1

的事情可能發生大量。您的Laps列表可能會被初始化,可能會被調整大小或分配。代碼可能是第一次碰到jvm,並需要額外的時間來運行。 jvm也可能會發現循環中沒有任何事情發生,並完全擺脫它。其他進程可能會獲得優先權,無數的事情。

+0

這是一個LinkedList,因此添加第一個元素和第1000個元素沒有區別。如果JVM移除了循環,那麼對於所有的圈來說不是這樣嗎? – rtheunissen