我正在运行一个非常简单的程序
static void Main(string[] args)
{
Console.WriteLine(Get4S());
Console.WriteLine(Get4());
}
private static int Get4S()
{
return 4;
}
private static int Get4()
{
int res = 0;
for (int i = 0; i < 4; i++)
{
res++;
}
return res;
}
当它在
x86
下工作时,它会内联Get4S
方法,而Get4
asm代码是:00000000 push ebp
00000001 mov ebp,esp
00000003 xor eax,eax
00000005 inc eax
00000006 inc eax
00000007 inc eax
00000008 inc eax
00000009 pop ebp
0000000a ret
但是在x64下运行时,我们为
Get4S
方法获得了相同的asm,但是Get4
asm并未完全优化:00000000 xor eax,eax
00000002 xor edx,edx
00000004 inc eax
00000006 inc edx
00000008 cmp edx,4
0000000b jl 0000000000000004
0000000d ret
我以为
x64
JIT展开了循环,然后看到可以在编译时计算结果,并且将内联具有编译时结果的函数。但是什么也没发生。为什么
x64
在这种情况下如此愚蠢? 最佳答案
我明白了。这是因为即使选择了x64
目标平台,在选择.Net 4.5.2
构建时也会使用RyuJIT。所以我通过在App.Config文件中添加此部分来修复它:
<configuration>
<runtime>
<useLegacyJit enabled="1" />
</runtime>
</configuration>
此标记启用“传统” x64 JIT(用引号引起来,因为我认为他比“发光的” RyuJIT更好),结果主要方法中的ASM为:
00000000 sub rsp,28h
00000004 mov ecx,4
00000009 call 000000005EE75870
0000000e mov ecx,4
00000013 call 000000005EE75870
00000018 nop
00000019 add rsp,28h
0000001d ret
两种方法都是在编译时计算的,并按其值进行内联。
结论:安装
.Net 4.6
时,对于RyuJIT
下的所有解决方案,旧的x64抖动将替换为CLR4.0
。因此,将其关闭的唯一方法是useLegacyJit
开关或COMPLUS_AltJit
环境变量关于c# - 为什么x86 JIT比x64更聪明?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29509304/