I was recently playing with some benchmarks and found very interesting results that I can't explain right now. Here is the benchmark:
@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); } } Result:
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 So there are two strange things here:
Arrays.copyOfis 2 times faster thanSystem.arraycopyfor small arrays (1,5,10 size). However, on a large array of size 1000Arrays.copyOfbecomes almost 2 times slower. I know that both methods are intrinsics, so I would expect the same performance. Where does this difference come from?- Manual copy for a 1-element array is faster than
System.arraycopy. It's not clear to me why. Does anybody know?
VM version: JDK 1.8.0_131, VM 25.131-b11
copyOfinternally usesarraycopy, your benchmark is the problem.Arrays.copyOfis JVM intrinsic. Once the method is JIT-compiled, Java code inArrays.javais not executed at all.Arrays.copyOf, because it has internal knowledge of what this method should do.