DEV Community

John Nyingi
John Nyingi

Posted on • Edited on

What is the best way to copy an array?

Once in a while, you come across a problem where you have an array a and you want to copy its values to array b. You use a technique you know works best or you use what is commonly suggested in the public forums.

But, have you ever wondered what is the fastest way you can copy an array? Well in this article we will benchmark different ways you can copy an array

Prelude

  • I'll be using .Net 7.0
  • We will copy values from the 0 index.
  • You can find the Complete Source Code here

Setup

I am using BenchmarkDotNet version 0.13.9, for testing I have 2 arrays Destination and a function that yields a small array and a big array.

private int[] Destination;

[GlobalSetup]
public void GlobalSetup()
{
    Destination = Enumerable.Range(0, 2048).ToArray();
}
public IEnumerable<object> GetIntArray()
{
    yield return Enumerable.Range(0, 10).ToArray();
    yield return Enumerable.Range(0, 1024).ToArray();
}
Enter fullscreen mode Exit fullscreen mode

We will copy the yielded arrays to the big array

ForLoop

A common way to copy an array is by use of a for loop like so;

[Benchmark]
[ArgumentsSource(nameof(GetIntArray))]
public void ForLoopCopy(int[] array)
{
    for (int i = 0; i < array.Length; i++)
    {
        Destination[i] = array[i];
    }
}
Enter fullscreen mode Exit fullscreen mode

If benchmark this test we get this result;
ForLoop Benchmark

That's fairly quick, I bet we can make it faster.

Array.Copy

Another technique commonly used to copy arrays is Array.Copy

[Benchmark]
[ArgumentsSource(nameof(GetIntArray))]
public void ArrayCopy(int[] array)
{
    Array.Copy(array, Destination, array.Length);
}
Enter fullscreen mode Exit fullscreen mode

It's quite simple to set up and how does it fair compared to the for loop?

Array Copy

that is a HUGE Leap, for large arrays we have a 14X improvement, and for small arrays, it's 2x improvement. Let's try another approach

Buffer.BlockCopy

This is also another way you can copy arrays.

[Benchmark]
[ArgumentsSource(nameof(GetIntArray))]
public void BufferBlockCopy(int[] array)
{
    Buffer.BlockCopy(array, 0, Destination, 0, array.Length * 4);
}
Enter fullscreen mode Exit fullscreen mode

Why do we multiply the length by 4? Well, BlockCopy copies bytes and int has 4 bytes.

BlockCopy

It's not as fast as the ArrayCopy for big arrays but it's roughly 2X slower than the Forloop for small arrays.

Span.CopyTo

Spans are contiguous regions of memory, the elements are tightly packed and aligned in one part of the memory. This means reading data can be much faster.

So lets create one;

[Benchmark]
[ArgumentsSource(nameof(GetIntArray))]
public void SpanCopy(int[] array)
{
    array.AsSpan().CopyTo(Destination);
}
Enter fullscreen mode Exit fullscreen mode

Caveate: We have to invoke AsSpan method to cast the array to a Span.

Span
It's performance is quite similar to the Array.Copy

Marshal.Copy

In Marshal copy we have to copy an array from managed memory to an unmanaged memory (IntPtr) and then copy from the unmanaged memory back to managed memory. So the code looks like this.

[Benchmark]
[ArgumentsSource(nameof(GetIntArray))]
public unsafe void MarshalCopy(int[] array)
{
    fixed (int* dstPtr = Destination)
    {
        IntPtr ptr = (IntPtr)dstPtr;
        Marshal.Copy(array, 0, ptr, array.Length);
    }
}
Enter fullscreen mode Exit fullscreen mode

How does it perform?

MarshalCopy

Well, it's nearly as fast as Array.Copy() for both small and large arrays.

Summary

What should you use, it is pretty clear that Array.Copy or Marshal or Span are more than sufficient ways for copying one array to another. You can use which ever approach that meets your needs.

Top comments (0)