JDK-6912521 : System.arraycopy works slower than the simple loop for little lengths
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: compiler
  • Priority: P5
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_vista
  • CPU: x86
  • Submitted: 2009-12-22
  • Updated: 2025-05-12
  • Resolved: 2015-02-20
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9 b55Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
A DESCRIPTION OF THE REQUEST :
When we copy one Java array to another, there are two possible ways: System.arraycopy method and the simple loop like this:
    for (int j = 0; j < a.length; j++)
        b[j] = a[j];
All Java tutorials recommend using System.arraycopy, when possible: it works faster and is written more shortly. Moreover, some professional IDEs, like IntelliJ IDEA, detect simple loops, like the loop above, and warn about a nonoptimal code.

However, for very short array (a.length=1,2,3), the testing shows that the simple loop works essentially faster then System.arraycopy. Below is a simple test illustrating this:

import java.util.Locale;

public class ArraycopySpeed {
    public static void main(String[] args) {
        if (args.length < 3) {
            System.out.println("Usage: " + ArraycopySpeed.class.getName()
                + " maxArrayLength loopLength numberOfIterations");
            return;
        }
        final int maxLen = Integer.parseInt(args[0]);
        final int n = Integer.parseInt(args[1]);
        int numberOfIterations = Integer.parseInt(args[2]);
        for (int iter = 1; iter <= numberOfIterations; iter++) {
            System.out.println("Test #" + iter);
            for (int len = 0; len < maxLen; len++) {
                int[] a = new int[len], b = new int[len];
                long t1 = System.nanoTime();
                for (int k = 0; k < n; k++) {
                    for (int j = 0; j < a.length; j++)
                        b[j] = a[j];
                }
                long t2 = System.nanoTime();
                for (int k = 0; k < n; k++) {
                    System.arraycopy(a, 0, b, 0, a.length);
                }
                long t3 = System.nanoTime();
                System.out.printf(Locale.US, "%d elements: %.3f ns simple loop, %.3f ns arraycopy %n",
                    len, (double)(t2 - t1) / n, (double)(t3 - t2) / n);
            }
            System.out.println();
        }
    }
}

On my computer (Intel Quad Core, Windows Vista-64, JVM 1.7.0-ea-b74, 64 bit) only for 5 or more elements System.arraycopy becomes the optimal solution. For  Is it possible to improve this behavior and always translate short arraycopy calls into an optimal code?


JUSTIFICATION :
If we need to copy short Java arrays in inner loops and this code is critical for the application performance, we are enforced to create an ugly code like the following:
if (a.length < 5) {
    for (int j = 0; j < a.length; j++)
        b[j] = a[j];
} else {
    System.arraycopy(a, 0, b, 0, a.length);
}
and there are no any guarantees that it will be the right choice for any JVMs. It can be really important, for example, if a Java array contains 2 or 3 coordinates in a plane or 3D space, and the algorithm copies one set of coordinates to another while processing millions of points. In my last module the Java array was used for storing a set of indexes in some multilevel histogram, and the number of indexes varies from 1 to 5-6.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
System.arraycopy should always work faster than an equivalent Java loop.
ACTUAL -
For short arrays (several elements) Java loop sometimes works faster than System.arraycopy.

---------- BEGIN SOURCE ----------
import java.util.Locale;

public class ArraycopySpeed {
    public static void main(String[] args) {
        if (args.length < 3) {
            System.out.println("Usage: " + ArraycopySpeed.class.getName()
                + " maxArrayLength loopLength numberOfIterations");
            return;
        }
        final int maxLen = Integer.parseInt(args[0]);
        final int n = Integer.parseInt(args[1]);
        int numberOfIterations = Integer.parseInt(args[2]);
        for (int iter = 1; iter <= numberOfIterations; iter++) {
            System.out.println("Test #" + iter);
            for (int len = 0; len < maxLen; len++) {
                int[] a = new int[len], b = new int[len];
                long t1 = System.nanoTime();
                for (int k = 0; k < n; k++) {
                    for (int j = 0; j < a.length; j++)
                        b[j] = a[j];
                }
                long t2 = System.nanoTime();
                for (int k = 0; k < n; k++) {
                    System.arraycopy(a, 0, b, 0, a.length);
                }
                long t3 = System.nanoTime();
                System.out.printf(Locale.US, "%d elements: %.3f ns simple loop, %.3f ns arraycopy %n",
                    len, (double)(t2 - t1) / n, (double)(t3 - t2) / n);
            }
            System.out.println();
        }
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Manual choosing between System.arraycopy and simple Java loop for a case of short arrays.

Comments
URL: http://hg.openjdk.java.net/jdk9/jdk9/hotspot/rev/54e0f8b411a8 User: lana Date: 2015-03-18 00:54:25 +0000
18-03-2015

URL: http://hg.openjdk.java.net/jdk9/hs-comp/hotspot/rev/54e0f8b411a8 User: roland Date: 2015-02-20 12:00:05 +0000
20-02-2015