通过数组访问数组巨大的性能损失

时间:2016-02-16 15:04:51

标签: java arrays performance

让我们看看以下两个java方法:

static void performance1() {
    int a=0; 
    int b=0;
    int[] arrayA = { 3, 4, 5 };
    int[] arrayB = { 4, 5, 6, 3, 4, 5, 6, 7, 8, 4 };
    long start = System.currentTimeMillis();
    for (int i = 0; i < 100000000; i++) {
        for (int k = 0; k < 100; k++) {
            a = arrayA[2];
            b = arrayB[1];
        }
    }
    long end = System.currentTimeMillis();
    System.out.println(end - start);

}

static void performance2() {
    int a=0; 
    int b=0;
    int[] arrayA = { 3, 4, 5 };
    int[] arrayB = { 4, 5, 6, 3, 4, 5, 6, 7, 8, 4 };
    long start = System.currentTimeMillis();
    for (int i = 0; i < 100000000; i++) {
        for (int k = 0; k < 100; k++) {
            b = arrayB[arrayA[2]];
        }
    }
    long end = System.currentTimeMillis();
    System.out.println(end - start);

}

第一种方法需要209 ms才能在我的系统上执行,即秒4295!这么多20倍。怎么会这样?据我所知,如果我声明3个单独的变量而不是arrayA,我可以获得20倍的性能提升,因为以下方法再次执行得非常快:

static void performance3() {
    int a=0; 
    int b=0;
    int[] arrayA = { 3, 4, 5 };
    int[] arrayB = { 4, 5, 6, 3, 4, 5, 6, 7, 8, 4 };
    long start = System.currentTimeMillis();
    for (int i = 0; i < 100000000; i++) {
        for (int k = 0; k < 100; k++) {
            b = arrayB[a];
        }
    }
    long end = System.currentTimeMillis();
    System.out.println(end - start);

}

我是否忽视了一些明显的东西?对我来说,差异是如此巨大,这真的让我感到惊讶。无论如何,谢谢你的解释:)

2 个答案:

答案 0 :(得分:1)

执行b = arrayB[1];时,它会直接引用位置1中存储的值,但当您执行b = arrayB[arrayA[2]];时,必须首先检索值arrayA[2],然后检索值arrayB[]的{​​{1}}基于前一步骤中的值检索。

编译器非常智能,可以在第一步中优化活动,但不能在第二步中优化活动。

如果查看这两种方法生成的字节代码,将会更清楚。

答案 1 :(得分:1)

在第一个代码中,a总是设置为5而b设置为5,无论你的循环索引是什么,所以编译器完全消除了循环,所以它最终会像:

int a=0; 
int b=0;
int[] arrayA = { 3, 4, 5 };
int[] arrayB = { 4, 5, 6, 3, 4, 5, 6, 7, 8, 4 };
long start = System.currentTimeMillis();
a = 5;
b = 5;
long end = System.currentTimeMillis();
System.out.println(end - start);