【问题标题】:Efficient System.arraycopy on multidimensional arrays多维数组上的高效 System.arraycopy
【发布时间】:2011-01-05 07:38:15
【问题描述】:

我知道常见的性能重构是将简单的for 替换为System.arraycopy.

我想问一下:

  1. system.arraycopy 究竟什么时候开始有意义(考虑到它是本机方法调用)。抄小东西说,

  2. 这是我的印象,还是不能简单地用arraycopy复制(有效)这样的循环:

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

【问题讨论】:

  • 如果您对性能非常着迷(除非您进行了基准测试并确定了瓶颈,否则您不应该如此),您通常可以将多维数组替换为一维数组。

标签: java arrays


【解决方案1】:

在我的用例中

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

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

比使用System.arraycopy 或直接的两个for 循环解决方案快方式
还使用原语(arrayCopy(int[][] array))进行了测试并得到了相同的结果。

【讨论】:

  • 不喜欢这个?也许要指出,该解决方案的功能性质不会对性能产生实质性影响,因为 99% 的实际工作都在 clone() 方法中。我将把这种方法添加到我的工具集中。
【解决方案2】:

使用 System.arraycopy 做一个快速的深拷贝并不难。下面是一个二维数组的例子:

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

根据快速时序测试,使用它复制 1000x1000 2D 数组 100 次需要 40 毫秒,而使用更明显的两个 for 循环和赋值需要 1740 毫秒。

【讨论】:

  • 我的要求是跳过第一行并创建一个包含其余行的新数组。所以,我修改如下。 for (int i = 1; i
【解决方案3】:

System.arrayCopy 可能是复制数组的最快方法,但它不会进行深度复制。

它也不能在你的第二个问题中做更复杂的例子。

【讨论】:

    【解决方案4】:

    与所有性能计时问题一样,您确实需要在您期望运行代码的环境中进行基准测试。不同的 JVM 版本和硬件(CPU、内存等)配置可能会产生不同的结果。这实际上取决于您的具体性能要求。

    但是,在进行这种级别的性能调整之前,您应该首先清楚地编写代码并使其正确。编译器和 JIT 将能够使用正常的算法表达式为您进行大量优化,但有时手动优化会混淆这些自动优化。在你有一个工作产品之后,如果性能不是你想要的,那么只对热点进行分析和工作。 (虽然有时对于更复杂的代码,您可能需要重构和/或更改您的逻辑。)

    在这种情况下,如果您复制整个数组,请使用System.arraycopy,因为这是执行此操作的标准方法。编译器现在或将来可能会为此提供额外的优化,因为核心 API 严重依赖于此,您可以放心,这是 JVM 开发人员一直希望以最佳方式运行的东西。

    您将需要运行一些循环,因为System.arraycopy 只能执行单个数组对象,而 Java 多维数组实际上是数组的数组。所以...

    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;
    }    
    

    或者你可以使用Arrays.copyOf,它使用System.arraycopy和一些内部反射(所以不如你自己直接使用System.arraycopy快),但不做深拷贝。

    【讨论】:

      【解决方案5】:

      AFAIK,System.arrayCopy 是复制数组的最有效和最佳方式。我不知道在任何情况下,实现自己的循环的替代方法对于直接复制会更有效。

      【讨论】:

        猜你喜欢
        • 2011-06-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-03
        • 1970-01-01
        • 2011-06-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多