2014-09-01 82 views
2

大多数表示,原始的对象存储在堆,但是,我从下面的性能测试不同的结果:对象,堆或栈中的原语?

public class Performance { 

long sum = 0; 

public static void main(String[] args) { 
    // TODO Auto-generated method stub 
    long startTime = System.currentTimeMillis(); 
    long pSum = 0; 
    for(int i = 0; i < Integer.MAX_VALUE; i++){ 
     pSum += i; 

    } 
    long endTime = System.currentTimeMillis(); 
    System.out.println("time of using primitive:" + Long.toString(endTime - startTime)); 
    System.out.println(pSum); 

    long startTime1 = System.currentTimeMillis(); 
    Long Sum = 0L; 
    for(int i = 0; i < Integer.MAX_VALUE; i++){ 
     Sum += i; 
    } 
    long endTime1 = System.currentTimeMillis(); 
    System.out.println("time of using object:" + Long.toString(endTime1 - startTime1)); 
    System.out.println(Sum); 

    Performance p = new Performance(); 
    long startTime2 = System.currentTimeMillis(); 
    for(int i = 0; i < Integer.MAX_VALUE; i++){ 
     p.sum += i; 
    } 
    long endTime2 = System.currentTimeMillis(); 
    System.out.println("time of using primitive in object:" + Long.toString(endTime2 - startTime2)); 
    System.out.println(p.sum); 
} 

}

结果是这样的:

time of using primitive:1454 
2305843005992468481 
time of using object:23870 
2305843005992468481 
time of using primitive in object:1529 
2305843005992468481 

我们可以发现在对象中使用基元和使用基元的时间几乎相同。所以我很困惑,如果对象中的原语存储在堆中。为什么在对象中使用基元和使用基元的时间成本几乎相同?

+3

google autoboxing,google JIT优化 – 2014-09-01 01:34:28

+1

“原始对象存储在堆中”是完全正确的:所有*对象*都在堆中,因此它们的内容也是如此。 – EJP 2014-09-01 01:47:41

+1

谨防从微基准中得出太多的推论。 – 2014-09-01 01:52:38

回答

1

当你去

Long sum; 
... 
sum += 1; 

的JVM,理论上,新龙每次分配,导致多头是不可改变。现在,一个非常聪明的编译器可以在这里做一些聪明的事情,但这解释了为什么你的第二个循环的时间更大。它正在分配Integer.MAXINT新的Sum对象。另一个原因自动装箱技术很棘手。

另外两个循环不需要分配新对象。一个使用原始int,另一个可以递增Performance.sum,而不需要每次都分配一个新的性能。如图所示,访问堆栈或堆中的原始int应该大致相同。

你的计时与堆与堆栈的访问速度很少有关,但是与循环中分配大量对象有关。

正如其他人所指出的,微基准可能会引起误解。