Why is Arrays.copyOf 2 times faster than System.arraycopy for small arrays?

后端 未结 1 1250
死守一世寂寞
死守一世寂寞 2021-02-14 06:56

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         


        
1条回答
  •  一向
    一向 (楼主)
    2021-02-14 07:24

    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?

    1. Without knowing how length relates to ar.length JVM needs to perform additional bounds check and be prepared to throw IndexOutOfBoundsException when length > ar.length.
    2. 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.

    0 讨论(0)
提交回复
热议问题