使用64位大小的结构时,请使用以下代码段
[StructLayout(LayoutKind.Explicit,Pack = 1,Size = 8)] unsafe struct BUF { } ((BUF*)dst) = *((BUF*)src);
产生
IL_0046: nop IL_0047: ldloc.s dst IL_0049: ldloc.2 IL_004a: ldobj MyClass/BUF IL_004f: stobj MyClass/BUF
*((long*)dst) = *((long*)src);
生产:
IL_0046: nop IL_0047: ldloc.s dst IL_0049: ldloc.2 IL_004a: ldind.i8 IL_004b: stind.i8
有没有人知道ldobj / stobj和ldind.i8 / stind.i8对于这个例子有什么区别?
ldobj / stobj似乎提高了20%的性能,但我无法弄清楚为什么会这样.这两条线是不是完全一样?
谢谢!
编辑:[64位释放模式]在发布模式下编译时,字节码看起来相同.性能测量不久前在发布模式下完成.
解决方法
我已经复制了你正在使用的两种不同的方法,并且看到生成了相同的IL,但是当在Release模式下运行时,两者的jitted代码完全相同:
这是我使用的测试方法:
using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace Test { [StructLayout(LayoutKind.Explicit,Size = 8)] unsafe struct BUF { } static class Program { static void Main() { BUF x,y,z; unsafe { Do1(&x,&y); Do2(&y,&z); } // Readline here to allow attaching debugger and dumping jitted code Console.ReadLine(); } // Disable inlining to permit easier identification of the code [MethodImpl(MethodImplOptions.NoInlining)] unsafe static void Do1(BUF* src,BUF* dst) { *((BUF*)dst) = *((BUF*)src); } // Disable inlining to permit easier identification of the code [MethodImpl(MethodImplOptions.NoInlining)] unsafe static void Do2(BUF* src,BUF* dst) { *((long*)dst) = *((long*)src); } } }
这两种方法的IL与您的匹配:
DO1:
IL_0000: ldarg.1 IL_0001: ldarg.0 IL_0002: ldobj Test.BUF IL_0007: stobj Test.BUF IL_000c: ret
DO2:
IL_0000: ldarg.1 IL_0001: ldarg.0 IL_0002: ldind.i8 IL_0003: stind.i8 IL_0004: ret
并转储jitted代码:
DO1:
Test.Program.Do1(Test.BUF*,Test.BUF*) Begin 000007ff00170190,size 7 000007ff`00170190 488b01 mov rax,qword ptr [rcx] 000007ff`00170193 488902 mov qword ptr [rdx],rax 000007ff`00170196 c3 ret
DO2:
Test.Program.Do2(Test.BUF*,Test.BUF*) Begin 000007ff001701b0,size 7 000007ff`001701b0 488b01 mov rax,qword ptr [rcx] 000007ff`001701b3 488902 mov qword ptr [rdx],rax 000007ff`001701b6 c3 ret
他们看起来和我完全一样.