Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8082991 | emb-9 | Roland Westrelin | P5 | Resolved | Fixed | team |
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.
- backported by
-
JDK-8082991 System.arraycopy works slower than the simple loop for little lengths
-
- Resolved
-
- relates to
-
JDK-8073957 assert(ary_src != 0) failed: not an array or instance?
-
- Resolved
-
-
JDK-8073624 Fix warning "converting to non-pointer type 'bool' from NULL" in arraycopynode.cpp
-
- Resolved
-
-
JDK-7173584 Implement arraycopy as a macro node
-
- Resolved
-
-
JDK-6700100 optimize inline_native_clone() for small objects with exact klass.
-
- Resolved
-
-
JDK-8073796 assert(check_obj_alignment(result)) failed: address not aligned: ...
-
- Resolved
-
-
JDK-8073792 assert((get_length_if_constant(phase) == -1) == !ary_src->size()->is_con()) failed: inconsistent
-
- Closed
-
-
JDK-8149758 Small arraycopy of non-constant length is slower than individual load/stores
-
- Open
-