如何在C#中实现Array.Copy?
我试着用ILSpy Array.Copy
C#中的Array.Copy
的实现,但它没有向我展示实现本身。
我写了一个简单的基准测试,Array.Copy和一个简单的for循环来复制数据。 Array.Copy更快。
如何更快地实施?
谢谢,谢伊
用于编写快速memcpy
函数的相同技术:
- 循环展开
- 以大块(通常使用SIMD)传输对齐数据
- CPU缓存提示(SIMD也有帮助)
也可以看看:
- 非常快速的图像处理memcpy?
- 如何提高memcpy的性能
- 使用SIMD指令重写memcpy / memcmp / …是有意义的
反汇编类会让你知道这个声明:
[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);
[MethodImpl]属性告诉JIT编译器该方法实际上是在CLR中实现的,用C ++而不是托管语言编写。 它查找方法名称表,并检索指向实现该方法的C ++函数的指针,并将其编译为简单的CALL指令。
获取CLR的源代码有点棘手,但SSCLI20版本对于已经存在很长时间并且不需要调整的方法非常准确。 Array.Copy()当然有资格。 我提到的表在clr \ src \ _vm \ ecall.cpp中定义,与您的问题相关的部分如下所示:
FCFuncStart(gArrayFuncs) FCFuncElement("Copy", SystemNative::ArrayCopy) FCFuncElement("Clear", SystemNative::ArrayClear) FCFuncElement("get_Rank", Array_Rank) // etc...
SystemNative :: ArrayCopy()函数指针将您带到clr \ src \ _vm \ comsystem.cpp。 实际的function太大了,无法复制到这里而不会让你的眼睛睁开,有很多错误检查正在进行。 它寻找一种优化副本的方法,幸运的情况是可以简单地复制数组的元素而不进行转换。 这是由名为m_memmove()的函数完成的。 您将在同一文件中找到该函数,它在32位版本的CLR中使用。
首先复制一个字节,直到目标地址在4个字节的倍数上对齐。 然后它一次复制16个字节,4次复制4次,这些复制很快,因为它们是对齐的。 然后它一次复制剩下一个字节的内容。
您现在可以看到为什么它比您自己的循环更快。 即使数组元素大小不是4字节宽,它也可以一次移动4个字节。 并且它可以在确保复制地址对齐的同时这样做,因为数组元素的物理地址是不可发现的。