Runtime: Add an additional overload to `Marshal.Copy`

Created on 30 Jul 2016  路  7Comments  路  Source: dotnet/runtime

Issue:
When writing interop code, it may be desirable to copy memory from one location to another. However, there is currently no managed API for doing so. As such, the user must manually implement such a function, which can be error prone and cannot take advantage of certain optimization techniques (such as using SIMD registers to copy aligned 16-byte blocks).

Workaround:
Use Buffer.MemoryCopy which is non-optimal for a few reasons (see https://github.com/dotnet/corefx/issues/10455#issuecomment-236372132), manually implement an API for marshalling memory, or DllImport the memcpy function from the C Runtime (this is non optimal as it does not necessarily exist in the same library on each platform).

Request:
An additional overload to Marshal.Copy should be provided in the form of public static void Copy(IntPtr source, IntPtr destination, int length). This would ideally end up as a call to memcpy behind the scenes.

api-needs-work area-System.Runtime.InteropServices tenet-performance

Most helpful comment

can end up using an intermediate buffer for copying

It won't ever use intermediate buffer for copying.

not able to take advantage of XMM copy

It does take advantage of the XMM copy for large sizes via the PInvoke to memmove. It is not easy to make it to take advantage of XMM copy, with taking all iteractions with GC and exception handling into account, not introducing too much extra overhead, and not having to maintain and test a customized version of thousands of lines of assembly.

Also, the world is moving in a direction where the fastest way to do memory copy is old-fashioned rep movsb again. Hopefully, all the tricky logic on choosing the best way to do memory copy that had to be updated for each major processor release will be just wired into the silicon in future.

All 7 comments

It may additionally be useful to provide other memory interop functions, such as memmove (uses an intermediate buffer, allowing the source and destination to overlap), memcmp (allows comparing of two memory blocks), memchr (allows locating the first instance of a value in a memory buffer), and memset (allows filling a memory buffer with the specified value).

public static void Copy(IntPtr source, IntPtr destination, int length)

Presumably the existing Buffer.MemoryCopy is not a good fit because it uses unsafe pointers instead of IntPtr?

@mikedn, there are three issues with Buffer.MemoryCopy:

  1. I didn't know it existed (this makes it a better workaround than implementing your own)
  2. Looking at the implementation, it is almost entirely implemented in managed code and is therefore not able to take advantage of XMM copy
  3. For large buffers (over 512 bytes), it falls back to calling memmove and can end up using an intermediate buffer for copying, thus slowing down performance.

Whether or not it the API is unsafe is of little consequence (at least to me) as I am already working with unsafe code and unmanaged memory.

can end up using an intermediate buffer for copying

It won't ever use intermediate buffer for copying.

not able to take advantage of XMM copy

It does take advantage of the XMM copy for large sizes via the PInvoke to memmove. It is not easy to make it to take advantage of XMM copy, with taking all iteractions with GC and exception handling into account, not introducing too much extra overhead, and not having to maintain and test a customized version of thousands of lines of assembly.

Also, the world is moving in a direction where the fastest way to do memory copy is old-fashioned rep movsb again. Hopefully, all the tricky logic on choosing the best way to do memory copy that had to be updated for each major processor release will be just wired into the silicon in future.

This should be taken care of by Span<T> and the optimizations that went into Buffer.MemoryCopy (the managed implementation takes advantage of XMM registers on x64 now).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bencz picture bencz  路  3Comments

jchannon picture jchannon  路  3Comments

GitAntoinee picture GitAntoinee  路  3Comments

EgorBo picture EgorBo  路  3Comments

chunseoklee picture chunseoklee  路  3Comments