2016-03-03 80 views
-2

考慮到下面的完整源代碼,請解釋爲什麼Eclipse中此程序的每次執行結果爲time,do1()大於time,do2() 2〜3毫秒。JVM - 速度性能問題

JVM是否需要「預熱」?

import java.util.concurrent.atomic.AtomicInteger; 
import java.util.stream.IntStream; 

public class Question { 
    public static void main(String[] args) { 
     do1(); 
     do2(); 
    } 

    public static void do1() { 
     O obj = new O(); 
     Thread t = new Thread(() -> IntStream.range(0, 100000) 
        .forEach(e -> obj.incrementN())); 

     long start = System.currentTimeMillis(); 

     t.start(); 

     try { 
      t.join(); 
     } catch (InterruptedException e1) { 

     } 

     float time = (System.currentTimeMillis()-start)/1000F; 

     System.out.println(time); 
     System.out.println(obj); 
     System.out.println(); 
    } 

    public static void do2() { 
     O obj = new O(); 
     Thread t = new Thread(() -> IntStream.range(0, 100000) 
        .forEach(e -> obj.incrementN())); 

     long start = System.currentTimeMillis(); 

     t.start(); 

     try { 
      t.join(); 
     } catch (InterruptedException e1) { 

     } 

     float time = (System.currentTimeMillis()-start)/1000F; 

     System.out.println(time); 
     System.out.println(obj); 
    } 
} 

class O { 
    private AtomicInteger n = new AtomicInteger(0); 

    public void incrementN() { 
     n.getAndIncrement(); 
    } 

    @Override 
    public String toString() { 
     return ""+n.get(); 
    } 
} 

輸出示例:

0.003 
100000 

0.001 
100000 
+1

如果你這樣做了1000次,然後拿出平均結果,這樣會更準確。這可能只是隨機性。 – Gendarme

+2

是的,JVM需要預熱,因爲大量使用的代碼通過JIT系統編譯爲本機代碼。 – Xvolks

+0

它只是一次性的結果,平均可以給出更準確的結果。 它可以加載在do1()中完成一次的類O的時間,然後在do2()中不花費時間。 –

回答

0

這的確是一個太短的時間跨度,以真正確定是什麼原因導致DO1()來執行比DO2長()。

一些因素可以是:

  • 垃圾收集器踢(創建例如你O和T對象,指針到其存儲位置(在棧上)被破壞時,方法DO1()留下,但記憶本身是由垃圾收集器釋放)

  • Eclipse中做了一些分析的東西在兩者之間(測量的變量,時間或東西)

  • 如你所說,在JVM可能也做一些熱身的東西。

  • 不利的CPU調度。這可能是因爲DO1()得到一些更多的CPU時間超過DO2(),無論出於何種原因

調用DO1()(或休眠)之前,你可以做一些東西,然後調用DO1(),然後再次等待並調用do2()並再次測量。或者你可以增加do1()和do2()消耗的時間量。另外,你的do1()和do2()方法(do1()中的name和println除外)完全相同,所以當你只調用do1()2次時會發生什麼?