我以前是Windows上的C++程序员。我知道编译器将优化C++中的三元操作符。
C++代码:
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
int result = argc > 3 ? 1 : 5;
printf("%d", result);
return 0;
}
由于管道的原因,生成的本机代码如下所示(当然,发布模型):
int result = argc > 3 ? 1 : 5;
00B21003 xor eax,eax
00B21005 cmp dword ptr [argc],3
00B21009 setle al
00B2100C lea eax,[eax*4+1]
C#代码:
namespace TernaryOperatorCSharp
{
static void Main(string[] args)
{
int argc = args.Length;
int result = argc > 1 ? 2 : 5;
System.Console.WriteLine(result);
}
}
我查找了生成的本机代码JIT,但是根本没有优化(仍然有两个跳转指令)。
int result = argc > 1 ? 2 : 5;
0000002f cmp dword ptr [ebp-4],1
00000033 jg 0000003F
00000035 nop
00000036 mov dword ptr [ebp-0Ch],5
0000003d jmp 00000046
0000003f mov dword ptr [ebp-0Ch],2
00000046 mov eax,dword ptr [ebp-0Ch]
00000049 mov dword ptr [ebp-8],eax
System.Console.WriteLine(result);
0000004c mov ecx,dword ptr [ebp-8]
0000004f call 6A423CBC
为什么C# JIT编译器不进行与C++编译器相同的优化?
这背后的故事是什么?
如有任何资料,将不胜感激。
你好,我已经修改了C#程序,并使用发布模型运行它。
先于
int result = args.Length > 1 ? 2 : 5;
Now
int argc = args.Length;
int result = argc > 1 ? 2 : 5;
但结果还是一样的。还有两个跳转指令。如果还有更多的信息,我将不胜感激。
发布于 2013-12-29 18:36:05
您不是在进行优化编译-- nop
指令说明了这一点(编译器将这些指令作为锚点插入,以便在大括号上放置断点)。
即使选中了“优化代码”复选框,Visual也不会总是生成优化代码。通常,当您在调试器中启动时,它无论如何都会禁用优化,这样调试会话就会像您预期的那样表现得更好。
此外,你不能把苹果和苹果作比较,因为苹果占了更多的便宜。
string[].Length
是C#中的属性,不是公共变量,而且也不是局部变量。通过使用代码,属性通常被视为公共变量,但实际上可以作为完整的get/set方法存在。编译器必须发出代码来处理这个问题,特别是当属性在单独的程序集中定义时。
使用本地int
变量尝试这个示例,并打开编译器优化(使用优化构建、启动程序、在启动后附加调试器、查看反汇编)。
发布于 2013-12-29 19:05:53
您正在查看程序的Debug构建。切换到发布版本。
您必须更改一个选项,以便在使用调试器查看反汇编时不会禁用优化器。工具+选项,调试,一般,取消“抑制JIT优化对模块加载”选项。
现在您将看到更紧凑的代码。x86抖动确实执行分支消除,并使用AGU作为数学,您可以看到它是在this answer中完成的,只是不在这里。如果您期望与C或C++编译器的优化器完全一致,那么抖动优化器将在相当严格的时间限制下运行,因为它在运行时运行。您将看到它在this answer中执行的优化大纲。
https://stackoverflow.com/questions/20827111
复制相似问题