如何在C#中复制非托管数据以及速度有多快?
我有两个IntPtr
forms的非托管指针,并希望在它们之间复制数据。 我怎样才能做到这一点? 我知道方法Marshal.Copy
,但它只能在非托管和托管之间进行复制。 第二部分:使用memcpy从C#中复制非托管数据比使用非托管C / C ++更慢吗?
编辑:我对平台独立实现特别感兴趣。
您可以通过P-Invoke使用win32 memcpy函数。
[DllImport("msvcrt.dll", SetLastError = false)] static extern IntPtr memcpy(IntPtr dest, IntPtr src, int count);
除了从托管代码调用win32函数的(轻微)开销之外,实际的复制性能应该与使用相同函数的C / C ++代码相同。
不要忘记您也可以使用不安全的块(和编译器选项),并且一次只能复制一个字节/ int / long的数据:
unsafe { // srcPtr and destPtr are IntPtr's pointing to valid memory locations // size is the number of long (normally 4 bytes) to copy long* src = (long*)srcPtr; long* dest = (long*)destPtr; for (int i = 0; i < size / sizeof(long); i++) { dest[i] = src[i]; } }
这将删除平台依赖关系,但您需要非常小心边界检查和指针算法。
没有对性能发表评论,纯粹是因为我没有测试过它。 通过使用来自内核的Kernel32中的CopyMemory或MoveMemory,您可以获得与非托管副本相同的性能。
这是CopyMemory的声明
[DllImport("kernel32.dll")] static extern void CopyMemory(IntPtr destination, IntPtr source, uint length);
如果可以使用.NET 4.6或更高版本,请尝试使用System.Buffer.MemoryCopy 。 我相信这个和使用P / Invoke的其他解决方案之间的主要区别在于,这种方法避免了较小尺寸的P / Invoke,只是直接进行复制。
以下是 .NET Core中实现的内容(最新版本为2018-06-19)。
CopyMemory
又名RtlCopyMemory
又名memcpy()
,无论是从C#还是C调用都是一样快(除了PInvoking方法本身的微小开销)。
但要记住的是,只有当您确定源和目标范围不重叠时才应使用CopyMemory
。 如果它们重叠,则需要使用MoveMemory
,这将更慢。
这是CopyMeSomeMemory
的声明,显示了在.Net中可以执行相同操作的不同方法:
[DllImport("kernel32.dll", EntryPoint = "RtlCopyMemory")] public static extern void CopyMeSomeMemory(IntPtr Destination, IntPtr Source, uint Length);
为了记录,我认为.Net中的Buffer.BlockCopy
也包含了其中一个function。