C#语言编译器是否自己执行任何实际优化?

时间:2016-01-29 19:00:18

标签: c# .net compiler-optimization

基于随机互联网评论,我一直认为C#编译器对IL 进行简单优化(删除always-true if语句,简单内联等),然后是JIT执行真实,复杂的优化。

仅作为一个例子,在the documentation for the /optimize compiler flag上,它说

  

/ optimize选项启用或禁用编译器执行的优化,以使输出文件更小,更快,更高效。

这意味着至少某些优化由语言编译器应用。

然而,玩Try Roslyn,这似乎不正确。看起来C#编译器根本就没有优化。

实施例

输入:

bool y = true;
if (y)
    Console.WriteLine("yo");

Decompiled output:

if (true)
{
    Console.WriteLine("yo");
}

输入:

static void DoNothing() { }

static void Main(string[] args)
{
    DoNothing();
    Console.WriteLine("Hello world!");
}

Decompiled output:

private static void DoNothing()
{
}
private static void Main(string[] args)
{
    NormalProgram.DoNothing();
    Console.WriteLine("Hello world!");
}

输入:

try
{
    throw new Exception();
}
catch (Exception)
{
    Console.WriteLine("Hello world!");
}

Decompiled output:

try
{
    throw new Exception();
}
catch (Exception)
{
    Console.WriteLine("Hello world!");
}

正如您所看到的,C#语言编译器似乎根本没有进行优化

这是真的吗?如果是这样,为什么文档声称/optimize会使您的可执行文件变小?

2 个答案:

答案 0 :(得分:3)

我能想到的唯一优化是C#编译器执行的实际操作使用反编译器是添加一个空的静态构造函数。

它们通常非常无趣,只是更紧凑的IL。你只能在看IL的时候看到它们,一个体面的反编译器不会显示它。未经优化的代码具有递归良好编译器的代码生成器的典型工件,冗余存储紧接着加载相同变量,分支到下一个地址。优化器知道如何消除它们。标准示例是为了帮助调试而发出的NOP,它们允许您在花括号上设置断点。由优化器删除。

没有什么可以提供轻松的可观察的性能提升,尽管你可能很幸运,更紧凑的IL恰好让抖动优化器有足够的时间来消除关键的内存存储。这种情况不会经常发生。

答案 1 :(得分:1)

/optimize标志对编译器说#34;嘿,这个代码试图尽可能优化"但这并不意味着那是圣杯旗帜优化 /optimize标志执行许多操作,例如删除未使用的变量,替换已声明的变量但未使用(例如您的示例),代码中的总数(例如int a = 2+2;变为int a = 4;以及许多其他事项cand find here