Why is System.arraycopy native in Java?

I was surprised to see in the Java source that System.arraycopy is a native method.

Of course, the reason is that it is faster. But what tricks is code that you can use to make it faster?

Why not just iterate over the original array and copy each pointer to a new array - is it really not so slow and cumbersome?

+73
java arrays native arraycopy
May 05 '10 at 10:01
source share
5 answers

In native code, this can be done with a single memcpy / memmove , unlike n different copy operations. The difference in performance is significant.

+68
May 05 '10 at 10:04 a.m.
source share

It cannot be written in Java. Native code can ignore or eliminate the difference between arrays of an object and arrays of primitives. Java cannot do this, at least not efficiently.

And it cannot be written with single memcpy() because of the semantics required by overlapping arrays.

+14
May 05 '10 at 10:09
source share

This, of course, is implementation dependent.

HotSpot will treat it as "internal" and paste the code into the call site. This is machine code, not the slow old C code. It also means that problems with the method signature go away to a large extent.

The simple copy cycle is simple enough so that obvious optimizations can be applied to it. For example, a scan cycle. What happens again depends on the implementation.

+9
May 05 '10 at 10:17
source share

In my own tests, System.arraycopy () for copying multiple dimensional arrays is 10-20 times faster than looping:

 float[][] foo = mLoadMillionsOfPoints(); // result is a float[1200000][9] float[][] fooCpy = new float[foo.length][foo[0].length]; long lTime = System.currentTimeMillis(); System.arraycopy(foo, 0, fooCpy, 0, foo.length); System.out.println("native duration: " + (System.currentTimeMillis() - lTime) + " ms"); lTime = System.currentTimeMillis(); for (int i = 0; i < foo.length; i++) { for (int j = 0; j < foo[0].length; j++) { fooCpy[i][j] = foo[i][j]; } } System.out.println("System.arraycopy() duration: " + (System.currentTimeMillis() - lTime) + " ms"); for (int i = 0; i < foo.length; i++) { for (int j = 0; j < foo[0].length; j++) { if (fooCpy[i][j] != foo[i][j]) { System.err.println("ERROR at " + i + ", " + j); } } } 

Fingerprints:

 System.arraycopy() duration: 1 ms loop duration: 16 ms 
+5
Nov 28 '11 at 2:44 p.m.
source share

There are several reasons:

  • JIT is unlikely to generate efficient low-level code like hand-written C code. Using low-level C can allow many optimizations that are almost impossible to do for a common JIT compiler.

    See this link for some tricks and speed comparisons of hand-written C implementations (memcpy, but the principle is the same): Check this Memcpy optimization improves speed

  • Version C is almost independent of the type and size of array elements. It is impossible to do the same in java, because there is no way to get the contents of the array as an raw block of memory (like a pointer).

+3
May 05 '10 at 10:15
source share



All Articles