开发者

Efficient System.arraycopy on multidimensional arrays

I'm aware that a common performance refactoring is to replace simple for's by System.arraycopy.

I want to ask about:

  1. When开发者_如何学JAVA exactly does system.arraycopy begin to make sense (considering it's a native method call). Does copying small things say, < 32 have any advantage?

  2. Is it my impression, or is it not simply possible to copy (efficiently) a cycle like this with arraycopy:

       for (int j = 0; j < 2; ++j) {
           vpr[m][s + j][i] = vr[j];
       }
    


It's not difficult to use System.arraycopy to do a quick deep copy. Here's an example for a 2D array:

for (int i = 0; i < src.length; i++) {
    System.arraycopy(src[i], 0, dest[i], 0, src[0].length);
}

From a quick timing test, using this to copy a 1000x1000 2D array 100 times takes 40 milliseconds, versus 1740 milliseconds using the more obvious two for loops and assignment.


Like all performance timing questions, you really need to benchmark in the environment where you are expecting to run your code. Different JVM versions and hardware (CPU, memory, etc) configurations may have different results. It really depends on your specific performance requirements.

But then, before getting to this level of performance tuning, you should first write the code clearly and make it right first. The compiler and JIT will be able to to a lot of optimizations for you with normal algorithm expressions but sometimes hand optimizations can confuse these automated optimizations. After you have a working product and if performance is not then what you would like, then profile and work on the hot spots only. (Though sometimes for more complex code you may need to refactor and/or change your logic.)

In this case, if you copying entire arrays then use System.arraycopy as this is the standard way to do that. The compiler may now or in the future provide additional optimizations for that since the core APIs rely on this heavily you can rest assured that this is something that the JVM developers always want to have running optimally.

You will need to run through some loops though since System.arraycopy can only do a single array object and with Java multi-dimension arrays are really arrays of arrays. So...

public int[][][] copyOf3Dim(int[][][] array) {
    int[][][] copy;
    copy = new int[array.length][][];
    for (int i = 0; i < array.length; i++) {
        copy[i] = new int[array[i].length][];
        for (int j = 0; j < array[i].length; j++) {
            copy[i][j] = new int[array[i][j].length];
            System.arraycopy(array[i][j], 0, copy[i][j], 0, 
                array[i][j].length);
        }
    }
    return copy;
}    

Or you could use Arrays.copyOf which uses System.arraycopy and some reflection internally (so is not as fast as directly using System.arraycopy yourself), but does not do a deep copy.


System.arrayCopy is likely the fastest way to copy an array, but it does not make deep copies.

It also cannot do the more complex example in your second question.


AFAIK, System.arrayCopy is the most efficient and best way to copy your arrays. I am not aware of any situations where the alternate way of implementing your own loops would be much more efficient for direct copies.


In my use case this

public <T> T[][] arrayCopy(T[][] array) {

    return Arrays.stream(array).
              map(el -> el.clone()).toArray(a -> array.clone());
}

was way faster than using System.arraycopy or the straight forward two for loops solution.
Also tested with primitives ( arrayCopy(int[][] array) ) and got the same result.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜