2011-11-18 171 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或其他东西;这应该消除在你正在进行的初始化期间垃圾收集的需要。