2014-06-19 48 views
6

我想知道为什么立即分配一个2D int数组(new int[50][2])比单独分配执行更差,即先执行new int[50][],然后再执行new int[2]一个接一个。这里是一个非专业的基准代码:2D阵列分配的性能

public class AllocationSpeed { 

    private static final int ITERATION_COUNT = 1000000; 

    public static void main(String[] args) { 
     new AllocationSpeed().run(); 
    } 

    private void run() { 
     measureSeparateAllocation(); 
     measureAllocationAtOnce(); 
    } 

    private void measureAllocationAtOnce() { 
     Stopwatch stopwatch = Stopwatch.createStarted(); 
     for (int i = 0; i < ITERATION_COUNT; i++) { 
      allocateAtOnce(); 
     } 
     stopwatch.stop(); 
     System.out.println("Allocate at once: " + stopwatch); 
    } 

    private int allocateAtOnce() { 
     int[][] array = new int[50][2]; 
     return array[10][1]; 
    } 

    private void measureSeparateAllocation() { 
     Stopwatch stopwatch = Stopwatch.createStarted(); 
     for (int i = 0; i < ITERATION_COUNT; i++) { 
      allocateSeparately(); 
     } 
     stopwatch.stop(); 
     System.out.println("Separate allocation: " + stopwatch); 
    } 

    private int allocateSeparately() { 
     int[][] array = new int[50][]; 
     for (int i = 0; i < array.length; i++) { 
      array[i] = new int[2]; 
     } 
     return array[10][1]; 
    } 
} 

我在64位Linux测试,这些结果与不同的64位甲骨文的Java版本:

1.6.0_45-B06:

Separate allocation: 401.0 ms 
Allocate at once: 1.673 s 

1.7.0_45-B18

Separate allocation: 408.7 ms 
Allocate at once: 1.448 s 

1.8.0-EA-b 115

Separate allocation: 380.0 ms 
Allocate at once: 1.251 s 

只是出于好奇,我的OpenJDK 7以及(其中的差异更小)试了一下:

Separate allocation: 424.3 ms 
Allocate at once: 1.072 s 

对我来说,这是相当反直觉的,我希望分配在一次快点。

+0

我已经尝试了不同的尺寸和对象[] []',没有任何改变。要么我真的很盲目,要么你发现了一些有趣的事情。或者JIT取消了我们的部分工作。 – maaartinus

回答

1

绝对令人难以置信。基准来源可能会受到优化,gc和JIT的影响,但这是什么?

综观java byte code instruction set

  • anewarray(+ 2个字节间接类指数)为对象类(A =地址)的阵列
  • newarray(+为prinitive类1个字节)对于基本类型的数组
  • multianewarray(+ 2字节间接类索引)多维数组

这导致人们怀疑multianewarray对于原始类型是次优的。

在进一步观察之前,我希望有人知道我们被误导的地方。

+2

字节码很难告诉我们关于速度的更多信息,因为它是JITC的速度。 – maaartinus

+1

你是否介意扩展为什么你认为'multianewarray'对于原语不太理想?我并不完全遵循你的推论。作为一个方面说明,我个人认为,你的答案会更适合作为评论,但它可能不是什么大问题...... – awksp

+0

似乎'multianew'已经失去了它的直接知识,即分配是关于原语的,反对'newarray'。它可能对每个'int []''做'a newarray'。但我并不是说这绝对如此。事实上,这将是一个糟糕的实施。 –