Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is Array.Copy implemented in C#?

Tags:

arrays

c#

I tried to look at the implementation of Array.Copy in C# with ILSpy but it didn't show me the implementation itself.

I wrote a simple benchmark, Array.Copy vs a simple for loop to copy the data. Array.Copy was faster.

How is it implemented faster?

Thanks, Shay

like image 326
Shay Ben Moshe Avatar asked Jul 02 '11 16:07

Shay Ben Moshe


People also ask

How do I copy part of an array to another array?

The Array. Copy() method in C# is used to copy section of one array to another array. Array. Copy(src, dest, length);

Can an array be copied?

Answer: There are different methods to copy an array. You can use a for loop and copy elements of one to another one by one. Use the clone method to clone an array. Use arraycopy() method of System class.


1 Answers

Disassembling the Array class will land you on this declaration:

[MethodImpl(MethodImplOptions.InternalCall), SecurityCritical, ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
internal static extern void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length, bool reliable);

The [MethodImpl] attribute tells the JIT compiler that the method is actually implemented in the CLR, written in C++ instead of a managed language. It looks in a table of method names and retrieves a pointer to the C++ function that implements the method and compiles it to a simple CALL instruction.

Getting the source code for the CLR is a bit tricky, but the SSCLI20 version is pretty accurate for methods that have been around for a long time and didn't require tweaking. Array.Copy() certainly qualifies. The table I mentioned is defined in clr\src\vm\ecall.cpp, the section that's relevant to your question looks like this:

FCFuncStart(gArrayFuncs)
    FCFuncElement("Copy", SystemNative::ArrayCopy)
    FCFuncElement("Clear", SystemNative::ArrayClear)
    FCFuncElement("get_Rank", Array_Rank)
    //  etc...

The SystemNative::ArrayCopy() function pointer takes you to clr\src\vm\comsystem.cpp. The actual function is too big to copy here without making your eyes glaze over, there is a lot of error checking going on. It looks for a way to optimize the copy, the happy case is where the elements of the array can simply be copied without being converted. That is done by a function named m_memmove(). You'll find that function in the same file, it is used in the 32-bit version of the CLR.

Which first copies a single byte at a time until the destination address is aligned on a multiple of 4 bytes. Then it copies 16 bytes at a time, 4 times 4, these copies are fast because they are aligned. Then it copies what's left one byte at a time.

You can perhaps now see why it can be faster than your own loop. It can move 4 bytes at a time even if the array element size is not 4 bytes wide. And it can do so while ensuring the copy address is aligned, you can't since the physical address of the array element isn't discoverable.

like image 154
Hans Passant Avatar answered Oct 14 '22 20:10

Hans Passant