James B
James B

Reputation: 3750

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 because it's faster. But what native tricks is the code able to employ that make it faster?

Why not just loop over the original array and copy each pointer to the new array - surely this isn't that slow and cumbersome?

Upvotes: 94

Views: 27930

Answers (6)

user746461
user746461

Reputation:

Late to the party. In my opinion, System.arraycopy is native mainly due to the distinction between primitive types and class types in Java. It's impossible to write a single method to deal with both, say int array, and String array.

Plus, System.arraycopy was introduced way before the pseudo generic type.

I find no one links a native implementation. In OpenJDK, the arraycopy Java method is implemented to eventually call copy_conjoint_atomic() which copies the arrary with a (while) loop, or call C++ memmove() if the element type is so-called primitive.

Upvotes: 1

Hrvoje Prgeša
Hrvoje Prgeša

Reputation: 2071

There are a few reasons:

  1. The JIT is unlikely to generate as efficient low level code as a manually written C code. Using low level C can enable a lot of optimizations that are close to impossible to do for a generic 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 Optimizing Memcpy improves speed

  2. The C version is pretty much independant of the type and size of the array members. It is not possible to do the same in java since there is no way to get the array contents as a raw block of memory (eg. pointer).

Upvotes: 4

user207421
user207421

Reputation: 310980

It can't be written in Java. Native code is able to ignore or elide the difference between arrays of Object and arrays of primitives. Java can't do that, at least not efficiently.

And it can't be written with a single memcpy(), because of the semantics required by overlapping arrays.

Upvotes: 16

Péter Török
Péter Török

Reputation: 116286

In native code, it can be done with a single memcpy / memmove, as opposed to n distinct copy operations. The difference in performance is substantial.

Upvotes: 87

jumar
jumar

Reputation: 5390

In my own tests System.arraycopy() for copying multiple dimension arrays is 10 to 20 times faster than interleaving for loops:

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);
        }
    }
}

This prints:

System.arraycopy() duration: 1 ms
loop duration: 16 ms

Upvotes: 4

Tom Hawtin - tackline
Tom Hawtin - tackline

Reputation: 147164

It is, of course, implementation dependent.

HotSpot will treat it as an "intrinsic" and insert code at the call site. That is machine code, not slow old C code. This also means the problems with the signature of the method largely go away.

A simple copy loop is simple enough that obvious optimisations can be applied to it. For instance loop unrolling. Exactly what happens is again implementation dependent.

Upvotes: 12

Related Questions