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.Throug
Your SystemArrayCopy
benchmark is not semantically equivalent to arraysCopyOf
.
It will be, if you replace
System.arraycopy(ar, 0, result, 0, length);
with
System.arraycopy(ar, 0, result, 0, Math.min(ar.length, length));
With this change the performance of both benchmarks will also become similar.
Why is the first variant slower then?
length
relates to ar.length
JVM needs to perform additional bounds check and be prepared to throw IndexOutOfBoundsException
when length > ar.length
.This also breaks the optimization to eliminate redundant zeroing. You know, every allocated array must be initialized with zeros. However, JIT can avoid zeroing if it sees that the array is filled right after creation. But -prof perfasm
clearly shows that the original SystemArrayCopy
benchmark spends significant amount of time clearing the allocated array:
0,84% 0x000000000365d35f: shr $0x3,%rcx
0,06% 0x000000000365d363: add $0xfffffffffffffffe,%rcx
0,69% 0x000000000365d367: xor %rax,%rax
0x000000000365d36a: shl $0x3,%rcx
21,02% 0x000000000365d36e: rep rex.W stos %al,%es:(%rdi) ;*newarray
Manual copy appeared faster for small arrays, because unlike System.arraycopy
it does not perform any runtime calls to VM functions.