【问题标题】:Does the C# language compiler perform any actual optimizations on its own?C# 语言编译器是否自行执行任何实际优化?
【发布时间】:2016-05-07 15:12:40
【问题描述】:

基于随机的 Internet cmets,我一直认为 C# 编译器对 IL 进行了简单的优化(删除始终为真的 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 会使您的可执行文件更小?

【问题讨论】:

  • 确实优化了y away...
  • 您真正需要做的是比较优化和非优化版本的 IL 代码。非反编译版本。
  • 你怎么知道这个在线编译使用了优化?
  • @ScottChamberlain 该站点也支持 IL 输出和非优化构建。

标签: c# .net compiler-optimization


【解决方案1】:

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

它们通常很无趣,只是更紧凑的 IL。您只能在查看 IL 时看到它们,一个像样的反编译器不会显示它。未优化的代码具有递归体面编译器的代码生成器的典型工件,冗余存储后立即加载相同的变量,分支到下一个地址。优化器知道如何消除它们。标准示例是发出以帮助调试的 NOP,它们允许您在花括号上设置断点。已被优化器移除。

没有什么可以提供容易可观察的性能改进,尽管您可能很幸运,更紧凑的 IL 恰好为抖动优化器提供了足够的时间来消除关键内存存储。这种情况并不经常发生。

【讨论】:

  • Eric Lippert 有一系列关于可空选项的文章。开关也得到了沉重的对待。基本上,JIT应该做什么。
【解决方案2】:

/optimize 标志对编译器说“嘿,这段代码尝试尽可能优化”,但这并不意味着这是圣杯标志优化。
/optimize 标志做了很多事情,比如删除未使用的变量,替换已声明但未使用的变量(如您的示例),代码中的总和(例如,int a = 2+2; 变为 int a = 4; 以及您可以找到的许多其他内容 here

【讨论】:

  • 请注意,无论是否启用优化,编译器都将使用像 2+2 这样的文字进行计算。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 2013-10-14
相关资源
最近更新 更多