7

This test

 for (;;) { int[] a = new int[10]; System.gc(); long t0 = System.currentTimeMillis(); for (int i = 0; i < 1000000; i++) { // int[] b = a.clone(); int[] b = Arrays.copyOf(a, a.length); } System.out.println(System.currentTimeMillis() - t0); } 

shows ~50ms for Arrays.copyOf and ~160 ms for clone. Clone is a special native method for making copies, why is it so slow?

I ran the test on my HotSpot Client JVM 1.7.0_11-b21. Note that when the array increases in size, the difference between clone and copyOf disappears.

3
  • clone is overloaded (because it must handle both pointer and scalar arrays), and, in the standard Sun/Oracle implementation, likely under-optimized. I've worked on implementations of clone that would most certainly do much better. Commented Feb 6, 2013 at 18:18
  • Also note that if you used larger arrays (say 10,000 elements) the numbers would likely be different. Commented Feb 6, 2013 at 18:21
  • Here is a reference to a bug you explain: bugs.sun.com/view_bug.do?bug_id=6428387 -- However you microbenchmark sucks - it's plain wrong Commented Feb 10, 2013 at 14:39

2 Answers 2

5

I ran your code on my system: there's virtually no difference between them. Both clock in at about 30 milliseconds. My test is on OpenJDK 7.

To confirm I also ran it through Caliper, and used a larger array to emphasize the actual copying performance:

public class Performance extends SimpleBenchmark { final int[] source = new int[1000]; public int timeClone(int reps) { int sum = 0; for (int i = reps; i > 0; i--) sum += source.clone().length; return sum; } public int timeCopyOf(int reps) { int sum = 0; for (int i = reps; i > 0; i--) sum += Arrays.copyOf(source,source.length).length; return sum; } public static void main(String... args) { Runner.main(Performance.class, args); } } 

Result:

 0% Scenario{vm=java, trial=0, benchmark=Clone} 2141.70 ns; σ=5416.80 ns @ 10 trials 50% Scenario{vm=java, trial=0, benchmark=CopyOf} 2168.38 ns; σ=1545.85 ns @ 10 trials benchmark us linear runtime Clone 2.14 ============================= CopyOf 2.17 ============================== vm: java trial: 0 

Per request, here it is with array size 10:

 0% Scenario{vm=java, trial=0, benchmark=Clone} 30.07 ns; σ=2.12 ns @ 10 trials 50% Scenario{vm=java, trial=0, benchmark=CopyOf} 29.34 ns; σ=161.38 ns @ 10 trials benchmark ns linear runtime Clone 30.1 ============================== CopyOf 29.3 ============================= 
Sign up to request clarification or add additional context in comments.

12 Comments

There is the possibility, that the complete loop is removed my the compiler. The cloned array points to an unused local variable. I am not sure, if the bytecode will contain that loop.
I ran the test on my HotSpot Client JVM 1.7.0_11-b21
@ChristianKuetbach HotSpot wouldn't dare eliminate a whole method call because it may have side-effects.
@Marko can you rerun your test with array size = 10?
Here is some proof, no need to test it: bugs.sun.com/view_bug.do?bug_id=6428387
|
0

I've found a good article explaining why clone is slow here http://www.javaspecialists.eu/archive/Issue124.html. To put it shortly, it's because int[].clone simply uses Object.clone and this method makes two checks before copying the array:

1.Check whether instance is normal object or array.

2.Check whether array is of primitives or objects.

I added these checks to the Arrrays.copyOf test

 for (int i = 0; i < 1000000; i++) { Class cls = a.getClass(); if (cls.isArray() && !cls.getComponentType().isAssignableFrom(Object.class)) { int[] b = Arrays.copyOf(a, a.length); } } 

and the test showed no difference between clone and Arrays.copyOf. Had it been a specialized version for arrays clone would have been fast.

1 Comment

a) That article is about Java 1.5, it's from 2006. b) Even considering their findings, note their conclusion: prefer clone to new+arraycopy because the code is simpler and copying performance is identical. Two simple if checks cannot possibly be a cause of performance degradation of any real piece of code.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.