我一直在嘗試測量System.arrayCopy與Arrays.copyOf的性能,以便正確選擇其中的一個。只是爲了基準,我添加了手冊,結果令我感到驚訝。 顯然我錯過了一些非常重要的東西,請問,請告訴我,它是什麼?實施如下(見前4種方法)。System.arrayCopy很慢
public class ArrayCopy {
public static int[] createArray(int size) {
int[] array = new int[size];
Random r = new Random();
for (int i = 0; i < size; i++) {
array[i] = r.nextInt();
}
return array;
}
public static int[] copyByArraysCopyOf(int[] array, int size) {
return Arrays.copyOf(array, array.length + size);
}
public static int[] copyByEnlarge(int[] array, int size) {
return enlarge(array, size);
}
public static int[] copyManually(int[] array, int size) {
int[] newArray = new int[array.length + size];
for (int i = 0; i < array.length; i++) {
newArray[i] = array[i];
}
return newArray;
}
private static void copyArray(int[] source, int[] target) {
System.arraycopy(source, 0, target, 0, Math.min(source.length, target.length));
}
private static int[] enlarge(int[] orig, int size) {
int[] newArray = new int[orig.length + size];
copyArray(orig, newArray);
return newArray;
}
public static void main(String... args) {
int[] array = createArray(1000000);
int runs = 1000;
int size = 1000000;
System.out.println("****************** warm up #1 ******************");
warmup(ArrayCopy::copyByArraysCopyOf, array, size, runs);
warmup(ArrayCopy::copyByEnlarge, array, size, runs);
warmup(ArrayCopy::copyManually, array, size, runs);
System.out.println("****************** warm up #2 ******************");
warmup(ArrayCopy::copyByArraysCopyOf, array, size, runs);
warmup(ArrayCopy::copyByEnlarge, array, size, runs);
warmup(ArrayCopy::copyManually, array, size, runs);
System.out.println("********************* test *********************");
System.out.print("copyByArrayCopyOf");
runTest(ArrayCopy::copyByArraysCopyOf, array, size, runs);
System.out.print("copyByEnlarge");
runTest(ArrayCopy::copyByEnlarge, array, size, runs);
System.out.print("copyManually");
runTest(ArrayCopy::copyManually, array, size, runs);
}
private static void warmup(BiConsumer<int[], Integer> consumer, int[] array, int size, int runs) {
for (int i = 0; i < runs; i++) {
consumer.accept(array, size);
}
}
private static void runTest(BiConsumer<int[], Integer> consumer, int[] array, int size, int runs) {
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
long currentCpuTime = threadMXBean.getCurrentThreadCpuTime();
long nanoTime = System.nanoTime();
for (int i = 0; i < runs; i++) {
consumer.accept(array, size);
}
System.out.println("-time = " + ((System.nanoTime() - nanoTime)/10E6) + " ms. CPU time = " + ((threadMXBean.getCurrentThreadCpuTime() - currentCpuTime)/10E6) + " ms");
}
}
結果表明,手動複製圍繞提高30%執行,如下圖所示:
****************** warm up #1 ******************
****************** warm up #2 ******************
********************* test *********************
copyByArrayCopyOf-time = 162.470107 ms. CPU time = 153.125 ms
copyByEnlarge-time = 168.6757949 ms. CPU time = 164.0625 ms
copyManually-time = 116.3975962 ms. CPU time = 110.9375 ms
我真的很困惑,因爲我認爲(也許我仍然這樣做)是System.arrayCopy
由於它的誕生是複製數組的最佳方法,但我無法解釋這個結果。
我猜測編譯器超過了你,並且把你的手動拷貝變成了一個arraycopy,但沒有Math.min,也沒有額外的函數間接尋址。此外,也許可以交換訂單幾次並記錄GC呼叫。 – TWT