2011-11-18 179 views
8

出於好奇,我測量了靜態塊和靜態方法初始值設定項之間的性能。首先,我實現上述方法在兩個獨立的Java類,像這樣:靜態塊vs靜態方法 - 初始化靜態域

第一:

class Dummy { 
    static java.util.List<Integer> lista = new java.util.ArrayList<Integer>(); 
    static { 
     for(int i=0; i < 1000000; ++i) { 
      lista.add(new Integer(i)); 
     } 
    } 
} 

public class First { 
    public static void main(String[] args) { 
     long st = System.currentTimeMillis(); 
      Dummy d = new Dummy(); 
     long end = System.currentTimeMillis() - st; 
     System.out.println(end);  
    } 
} 

第二:

class Muddy { 
    static java.util.List<Integer> lista = new java.util.ArrayList<Integer>(); 
    public static void initList() { 
     for(int i=0; i < 1000000; ++i) { 
      lista.add(new Integer(i)); 
     } 
    } 
} 

public class Second { 
    public static void main(String[] args) { 
     long st = System.currentTimeMillis(); 
      Muddy.initList(); 
      Muddy m = new Muddy(); 
     long end = System.currentTimeMillis() - st; 
     System.out.println(end);  
    } 
} 

然後我執行this小批量腳本,對它進行測量100時間並將這些值放入一個文件中。 batchFile.bat First Second dum.res.txt

之後,我寫了this一段代碼來計算Dummy和Muddy測量值的平均值和標準偏差。

這是我已經得到了結果:

First size: 100 Second size: 100 
First  Sum: 132 Std. deviation: 13 
Second  Sum: 112 Std. deviation: 9 

而且這是在我的其他機器相似......我每次測試時間。

現在我在想,爲什麼這樣呢?我檢查了字節碼,Second.class在調用System.currentTimeMillis()之間多了一個指令(調用靜態initList())。 他們都做同樣的事情,但爲什麼第一個更慢?我不能僅僅通過查看字節碼來推理它,因爲這是我第一次碰到javap;我還不懂字節碼。

+0

嘗試在調用批處理腳本時查看第一個和第二個查看結果是什麼:) – antlersoft

+0

指令的數量與這些指令需要多長時間無關(告訴您開車穿過城鎮與全國各地 - 好吧,除非你住在Lichenstein或其他地方)。他們是完全一樣的說明嗎?我相當懷疑這一點。在附註中,即使速度更快,我也會猶豫是否使用第二個版本 - 它依賴於進行initList()調用,這是我永遠不會指望的。 –

+0

@antlersoft它返回相同的結果。已經測試過它。 – Mechkov

回答

2

這是我對此的猜測:

您正在做的初始化是創建足夠多的對象,導致一個或多個垃圾回收。

當從靜態塊調用初始化時,它在類初始化期間完成,而不是在簡單方法執行期間完成。在類初始化期間,即使堆的內容幾乎相同,垃圾檢測器可能還有更多工作要做(比如,執行堆棧比較長)。

爲了測試這個,你可以嘗試在你的java命令中加入-Xms200m或其他東西;這應該消除在你正在進行的初始化期間垃圾收集的需要。