多维数组上的高效System.arraycopy

我知道一个常见的性能重构是用System.arraycopy.替换simple for System.arraycopy.

我想问一下:

  1. 什么时候system.arraycopy开始有意义(考虑到它是一个本机方法调用)。 复制小事说,<32有什么优势吗?

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

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

System.arrayCopy可能是复制数组的最快方法,但它不会生成深层副本。

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

使用System.arraycopy进行快速深层复制并不困难。 以下是2D数组的示例:

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

从快速计时测试中,使用它来复制1000x1000 2Darrays100次需要40毫秒,相比之下1740毫秒使用更明显的两个for循环和分配。

与所有性能计时问题一样,您确实需要在您希望运行代码的环境中进行基准测试。 不同的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和一些reflection(所以不像你自己直接使用System.arraycopy那么快),但是不做深度复制。

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

在我的用例中

 public  T[][] arrayCopy(T[][] array) { return Arrays.stream(array). map(el -> el.clone()).toArray(a -> array.clone()); } 

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