我试着Array.Copy用ILSpy 查看C#中的实现,但它没有向我展示实现本身.
我写了一个简单的基准测试,Array.Copy与一个简单的for循环来复制数据.Array.Copy更快.
如何更快地实施?
谢谢,谢伊
Han*_*ant 25
反汇编类将使您获得此声明:
[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);
Run Code Online (Sandbox Code Playgroud)
[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...
Run Code Online (Sandbox Code Playgroud)
SystemNative :: ArrayCopy()函数指针将您带到clr\src\_vm\comsystem.cpp.实际的功能太大了,无法复制到这里而不会让你的眼睛睁开,有很多错误检查正在进行中.它寻找一种优化副本的方法,幸运的情况是可以简单地复制数组的元素而不进行转换.这是由名为m_memmove()的函数完成的.您将在同一文件中找到该函数,它在32位版本的CLR中使用.
首先复制单个字节,直到目标地址在4个字节的倍数上对齐.然后它一次复制16个字节,4次复制4次,这些复制很快,因为它们是对齐的.然后它一次复制剩下一个字节的内容.
您现在可以看到为什么它比您自己的循环更快.即使数组元素大小不是4字节宽,它也可以一次移动4个字节.并且它可以在确保复制地址对齐的同时这样做,因为数组元素的物理地址是不可发现的.
Ben*_*igt 11
用于编写快速memcpy函数的相同技术:
也可以看看: