Gần đây tôi đã chơi với một số điểm chuẩn và tìm thấy kết quả rất thú vị mà tôi không thể giải thích ngay bây giờ. Dưới đây là điểm chuẩn:Tại sao Arrays.copyOf nhanh hơn 2 lần so với System.arraycopy cho mảng nhỏ?
@BenchmarkMode(Mode.Throughput)
@Fork(1)
@State(Scope.Thread)
@Warmup(iterations = 10, time = 1, batchSize = 1000)
@Measurement(iterations = 10, time = 1, batchSize = 1000)
public class ArrayCopy {
@Param({"1","5","10","100", "1000"})
private int size;
private int[] ar;
@Setup
public void setup() {
ar = new int[size];
for (int i = 0; i < size; i++) {
ar[i] = i;
}
}
@Benchmark
public int[] SystemArrayCopy() {
final int length = size;
int[] result = new int[length];
System.arraycopy(ar, 0, result, 0, length);
return result;
}
@Benchmark
public int[] javaArrayCopy() {
final int length = size;
int[] result = new int[length];
for (int i = 0; i < length; i++) {
result[i] = ar[i];
}
return result;
}
@Benchmark
public int[] arraysCopyOf() {
final int length = size;
return Arrays.copyOf(ar, length);
}
}
Kết quả:
Benchmark (size) Mode Cnt Score Error Units
ArrayCopy.SystemArrayCopy 1 thrpt 10 52533.503 ± 2938.553 ops/s
ArrayCopy.SystemArrayCopy 5 thrpt 10 52518.875 ± 4973.229 ops/s
ArrayCopy.SystemArrayCopy 10 thrpt 10 53527.400 ± 4291.669 ops/s
ArrayCopy.SystemArrayCopy 100 thrpt 10 18948.334 ± 929.156 ops/s
ArrayCopy.SystemArrayCopy 1000 thrpt 10 2782.739 ± 184.484 ops/s
ArrayCopy.arraysCopyOf 1 thrpt 10 111665.763 ± 8928.007 ops/s
ArrayCopy.arraysCopyOf 5 thrpt 10 97358.978 ± 5457.597 ops/s
ArrayCopy.arraysCopyOf 10 thrpt 10 93523.975 ± 9282.989 ops/s
ArrayCopy.arraysCopyOf 100 thrpt 10 19716.960 ± 728.051 ops/s
ArrayCopy.arraysCopyOf 1000 thrpt 10 1897.061 ± 242.788 ops/s
ArrayCopy.javaArrayCopy 1 thrpt 10 58053.872 ± 4955.749 ops/s
ArrayCopy.javaArrayCopy 5 thrpt 10 49708.647 ± 3579.826 ops/s
ArrayCopy.javaArrayCopy 10 thrpt 10 48111.857 ± 4603.024 ops/s
ArrayCopy.javaArrayCopy 100 thrpt 10 18768.866 ± 445.238 ops/s
ArrayCopy.javaArrayCopy 1000 thrpt 10 2462.207 ± 126.549 ops/s
Vì vậy, có hai điều lạ ở đây:
Arrays.copyOf
nhanh hơnSystem.arraycopy
2 lần cho nhỏ mảng (1,5 , 10 kích thước). Tuy nhiên, trên một mảng lớn có kích thước 1000Arrays.copyOf
trở nên chậm hơn gần 2 lần. Tôi biết rằng cả hai phương pháp là nội tại, vì vậy tôi mong đợi cùng một hiệu suất. Trường hợp sự khác biệt này đến từ đâu?- Bản sao thủ công cho mảng 1 phần tử nhanh hơn
System.arraycopy
. Nó không rõ ràng với tôi tại sao. Có ai biết không?
VM phiên bản: JDK 1.8.0_131, VM 25,131-b11
Vì 'copyOf' sử dụng nội bộ' mảng bản đồ', điểm chuẩn của bạn là vấn đề. – Andreas
@Andreas Bạn không đúng. 'Arrays.copyOf' là JVM nội tại. Khi phương thức được biên dịch JIT, mã Java trong 'Arrays.java' không được thực thi. – apangin
@Andreas Bạn có thấy bất kỳ vấn đề cụ thể nào với điểm chuẩn không? Nó sử dụng một cách khôn ngoan [khuôn khổ JMH] (http://openjdk.java.net/projects/code-tools/jmh/) để tránh những cạm bẫy chuẩn. – apangin