多维数组上的高效System.arraycopy
我知道一个常见的性能重构是用System.arraycopy.
替换simple for
System.arraycopy.
我想问一下:
-
什么时候system.arraycopy开始有意义(考虑到它是一个本机方法调用)。 复制小事说,<32有什么优势吗?
-
这是我的印象,还是不可能简单地使用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)
)进行测试并得到相同的结果。