c# - .NET 在编译前会优化代码吗?

标签 c# compiler-construction jit

我正在浏览我的代码,我想起了 ActionScript 编译器所做的事情:它简化了不必要/冗余的代码,然后编译结果。我想知道 C# 是否有相同的过程。

如果我的理解正确,并假设这将是有效的 ActionScript(我知道它不是),编译器将采用以下内容:

byte[] result = ServerWC.UploadValues("http://localhost", srvNvc);
Console.WriteLine(Encoding.ASCII.GetString(result));

并将其简化为:

Console.WriteLine(Encoding.ASCII.GetString(ServerWC.UploadValues("http://localhost", srvNvc)));

编译前。哪种编译器(C#->IL 或 IL->machine)会进行优化?所有编译器都这样工作吗?

最佳答案

您发布的代码中没有任何不必要的内容。您的更改根本没有真正进行任何简化 - 您只是将伪命令代码块更改为单个表达式。

.NET 编译过程有点复杂 - 首先,您拥有安全的托管 C#。然后,您就拥有了安全、受管理的 IL。最后,您得到不安全的 native x86 程序集(例如)。

IL 基本上是基于堆栈的。所以你的代码会变成这样:

call UploadValues
call Encoding::ASCII
call Encoding.GetString
call Console::WriteLine

(不用说,这严重过于简化 - 但它是一种相当高级的“类似汇编”语言)

您可以看到,即使在这里,也不再有任何局部变量,真的。它只是虚拟堆栈上的一个值。当然,不同的编译器有权以不同的方式实现这一点。例如,您可能会得到如下内容:

call UploadValues
stloc.0
ldloc.0
call Encoding::ASCII
call Encoding.GetString
call Console::WriteLine

但很明显,这确实是一个额外的步骤,而不是缺失的优化:)

不过,新的 Roslyn 编译器确实利用了旧编译器没有的一些功能。例如,如果在同一个方法中多次使用同一个本地变量,它也有可能避免使用本地变量 - 今天的问题 VS2015 stloc.0 and ldloc.0 are removed from compilation instructions 就是一个很好的例子。 .

但是,这里发生的任何事情都不一定会影响结果代码的性能。下一步,从 IL 到 x86 的 JIT 编译,是完成大部分优化的部分。其中包括诸如决定 IL 中的局部变量和虚拟堆栈将表示为寄存器中的值之类的事情。

对于 ActionScript,我认为从 AS3 开始也是如此。旧的解释版本中可能存在差异,但当它跳转到完整的 JIT 虚拟机时,这种差异可能消失了。

关于c# - .NET 在编译前会优化代码吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32741478/

相关文章:

C# 在小函数上的性能

c# - 使用 C# 在 Azure 中的存储容器之间复制 blob

c# - .NET 中接口(interface)的部分显式实现

由列和行字符串值键入的 C# 矩阵

c# - 如何在运行时在安装程序类中获取路径 'C:\inetpub\wwwroot\wss\VirtualDirectories' (c#)

java - JIT 不编译大型方法的理由是什么?

css - SASS 定期将代码注释插入我编译的 CSS 中

c++ - 编译器标志 -l 的位置

c++ - g++ 不喜欢模板 var 上的模板方法链接?

java - 为什么 JIT 也编译字节码而 Java 既是编译型又是解释型语言?