Why Arrays.copyOf so slow?

system arraycopy performance
arrays copyof vs clone
java array copy vs clone
copy vs clone java
arrays stream filter
java arrays
copyarray
java system arraycopy byte array

The function ArrayList.add() works very fast. I checked the source code, and saw the implement was Arrays.copyOf()

private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

But when I use the method Arrays.copyOf() in my code, it becomes very slow. You can just run the code below to see it:

public class TestArrayCopy {
  public static void main(String[] args) {
    long t = System.currentTimeMillis();
    List<Integer> list = new ArrayList<>();
    for (int i = 0; i < 100000; i++) {
      list.add(i, i);
    }
    System.out.println(System.currentTimeMillis() - t);

    t = System.currentTimeMillis();
    Integer[] array = new Integer[0];
    for (int i = 0; i < 100000; i++) {
      array = Arrays.copyOf(array, array.length +1);
      array[i] = i;
    }
    System.out.println(System.currentTimeMillis() - t);
  }
}

Any ideas?

[JavaSpecialists 124], but explain why the cloning is so much slower for small arrays. arrayCopy() method uses JNI to copy the memory and I knew that was fast. 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.

If you are asking why the two loops have a different running time (the second being much slower), the reason is that most calls to list.add(i, i) don't need to re-create the backing array.

Only when the backing array becomes full, a larger array is created. And the larger array is 50% larger than the original array, so it can handle many subsequent calls to add before it becomes full.

JDK-6428387 array clone() much slower than Arrays.copyOf, JDK-6428387 : array clone() much slower than Arrays. copyOf(a, 1) or Object[] x = new Object[1]; System.arraycopy(a, 0, x, 0, 1); but it is in fact much slower. But why is it so slow for what are very simple things that should be nearly instantaneous. For example, if I want to adjust the symbology of something, ever single step causes the program to whir and think for about ten seconds, even when the layer is turned off!

Arrays.copyOf is as slow as expected. Whileas List.add() is as quick as expected, since Arrays.copyOf in the grow method doesn't occur every time the add method is called. grow only occurs when the capability of the ArrayList is not enough.

Deep dive into the clone vs copy question, Clone is faster for array copy, noticeably on small arrays. Arrays.copyOf the clone benchmark is more than 4 times slower! What happened? Why is the Epic Games Launcher so freaking slow!? If you have ever used the launcher in question you will know it takes an absolute century to download and install your games. All you have to do is a simple Google search and you will see there are hundreds if not thousands of people complaining about the speed.

Because grow() is not always called when a new element is added. The ArrayList is always increased by a factor of 50%.

The relevant lines are those:

int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);

The (oldCapacity >> 1) is doing a bit shift to the right, so dividing by 2. This means that newCapacity is +50% of oldCapacity. Only if this is exceeded, the next call to grow() is made.

Arrays (Java Platform SE 8 ), Copies the specified array, truncating or padding with false (if necessary) so the copy has the specified length. static byte[], copyOf(byte[] original, int newLength). RELATED: Why Rebooting Your Router Fixes So Many Problems (and Why You Have to Wait 10 Seconds) Like computers, modems and routers sometimes get stuck in a bad, slow, overloaded state. This problem can be fixed with a reboot. If you haven’t rebooted your router and modem in a while, you should do it now.

The difference is amortized runtime. Your implementation copies the entire array each time a new copy is created. Each copy-operation is O(n), making the cost of the entire operation

1 + 2 + ... + n = n * (n + 1) / 2 = O(n^2)

grow on the other hand increases the size in a different manner. The new size of the array is calculated in this line:

int newCapacity = oldCapacity + (oldCapacity >> 1);

which essentially boils down to

int newCapacity = (int) (oldCapacity * 1.5)

So once the array is filled up, the array grows by a factor of 1.5

This in comparison takes for n insertions and an initial size m

m + 1.5 * m + 1.5 ^ 2 * m + ... + n = 
m + 1.5 * m + 1.5 ^ 2 * m + ... + 1.5 ^ log_1.5(n / m) * m = 
m * (1 - 1.5 ^ (log_1.5(n / m) + 1) / (1 - 1.5) = 
m * 2 * (n / m * 1.5 - 1) =
3 * n - 2 * m

The amortized runtime can be calculated as the total cost for n insertions divided by n:

(3 * n - 2 * m) / n = 3 - 2 * m / n

Since m < n in your case the second part of the equation becomes negligible, and we we end up with O(1) as amortized runtime and a runtime for all insertions of O(n), which significantly differs from the O(n^2) for copying the entire array after each insert.

3 Good Reasons to Avoid Arrays in Java Interfaces, How can using a plain array be slower than using an object that However, if the method returns a List , creating the defensive copy is yet  You notice your laptop began to act up, for example, taking longer to start up, freezing now and then, and many a time you couldn’t help but scream out: why is my laptop so slow? If this sounds familiar to you, then you come to the right place. Here we are going to show you the common causes for a slow laptop and what you can do to fix them.

[Performance] Is OpenJ9 slower than Hotspot in this specific case , copyOf is invoked Lastly, If you're wondering why I'm using ArrayLists instead of normal arrays, it's because my PC ran faster when using these  As to why Google would do this, Peterson wrote, "I assume Google has metrics showing that the Polymer redesign increases Firefox and Edge user engagement more than the slow polyfills hurt it

Arrays \ Processing.org, The syntax and usage of arrays is discussed in more detail in the following pages​. arrays, to avoid unnecessary copying of data that can slow down a program. The most common way to copy elements from one array to another is to use  These silent performance hogs slip under the radar, leaving you in a state of distress wondering why your laptop is so slow. Quick fix: Close those browsers. You may want to go to your browsing history and delete computer cookies and cached items as well for even more of a boost in laptop speed.

Copying Arrays in Java 6, They also demonstrate that copyOf is a mite slower than arraycopy . It's probably not enough for me to worry about, so I'll use the new copyOf  So, imagine the annoyance for Google Chrome users when the browser coveted for its speediness responds frustratingly slow. Fortunately, there's often an easy fix. Check out the products mentioned

Comments
  • Because it doesn't always happen when grow is called?
  • You should read source code more carefully so you will notice that Arrays.copyOf don't occur every time the add method is called.
  • Thanks, I should read more carefully!
  • BTW see also stackoverflow.com/questions/504103/…