Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 二维阵列分配的性能_Java_Arrays_Performance - Fatal编程技术网

Java 二维阵列分配的性能

Java 二维阵列分配的性能,java,arrays,performance,Java,Arrays,Performance,我想知道为什么一次分配2D int数组(new int[50][2])的性能比单独分配差,也就是说,先执行new int[50][,然后逐个执行new int[2]。以下是一个非专业的基准代码: public class AllocationSpeed { private static final int ITERATION_COUNT = 1000000; public static void main(String[] args) { new Alloca

我想知道为什么一次分配2D int数组(
new int[50][2]
)的性能比单独分配差,也就是说,先执行
new int[50][
,然后逐个执行
new int[2]
。以下是一个非专业的基准代码:

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];
    }
}
1.7.0_45-b18

Separate allocation: 408.7 ms
Allocate at once: 1.448 s
1.8.0-ea-b115

Separate allocation: 380.0 ms
Allocate at once: 1.251 s
出于好奇,我也尝试了OpenJDK 7(差别较小):

对我来说,这是非常违反直觉的,我希望立即分配会更快。

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

查看以下内容:

  • anewarray(+2字节间接类索引)用于对象类数组(a=地址)
  • newarray(+1字节用于prinitive类)用于基本类型的数组
  • 多维数组的multianewarray(+2字节间接类索引)
这导致人们怀疑multianewarray对于基本类型来说是次优的


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

后一种代码的内部循环(带有
newarray
)比前一种代码的
multi-anewarray
)被击中的次数更多,因此它可能会更快地击中C2并进行逃逸分析。(一旦发生这种情况,后一种代码创建的行将分配到堆栈上,这比堆快,并减少了垃圾收集器的工作负载。)


也有可能这些JDK版本实际上没有对
multianewarray
中的行进行转义分析,因为多维数组更有可能超过堆栈数组的大小限制。

字节码几乎没有比源代码告诉我们更多关于速度的信息,因为JITC决定了速度。您是否介意进一步说明为什么您认为
multianewarray
对于原语来说是次优的?我不太明白你的推论。作为旁注,我个人认为As is您的答案更适合作为注释,但这可能不是什么大问题……似乎
multianew
已经失去了它的直接知识,即分配是关于原语的,而不是
newarray
。它可能会对每个
int[]
执行类似
anewarray
的操作。但我并不认为这是绝对正确的。事实上,这将是一个糟糕的实现。为什么那个实现会是糟糕的呢?它在本质上不是等同于OP的代码吗?关于原语信息丢失的原因,我想到的第一件事是,这可能是为了处理任意嵌套的数组,但我怀疑这是对的……但我只是用相同的结果复制了它。我尝试了不同大小和
Object[][]
,但没有任何改变。不是我真的瞎了,就是你发现了有趣的东西。或者JIT比我们聪明,并且消除了部分工作。
Separate allocation: 380.0 ms
Allocate at once: 1.251 s
Separate allocation: 424.3 ms
Allocate at once: 1.072 s