C#编译器优化那点事

使用C#编写程序,给最终用户的程序,是需要使用release配置的,而release配置和debug配置,有一个关键区别,就是release的编译器优化默认是启用的。
优化代码开关即optimize开关,和debug开关一起,有以下几种组合。

C#编译器优化那点事

在Visual Sutdio中新建一个C#项目时,
项目的“调试”(Debug)配置的是/optimize-和/debug:full开关,
而“发布”(Release)配置指定的是/optimize+和/debug:pdbonly开关

optimize-/+决定了编译器是否优化代码,optimize-就是不优化了,但是通常,有一些基本的“优化”工作,无论是否指定optimize+,都会执行。

optimize- and optimize+

该项功能主要用于动态语义分析,帮助我们更好地编写代码。

常量计算

在写程序的时候,有时能看见代码下面划了一道红波浪线,那就是编译器动态检查。常量计算,就是这样,编译器会计算常量,帮助判断其他错误。

C#编译器优化那点事

简单分支检查

如果swtich写了两个以上的相同条件,或者分支明显无法访问到,都会弹出提示。

C#编译器优化那点事

未使用变量

不多说明,直接看图。

C#编译器优化那点事

使用未赋值变量

不多说,看图。

C#编译器优化那点事

局限

使用变量参与计算,随便写一个算式,就可以绕过一些检查,虽然我们看来是明显有问题的。

C#编译器优化那点事

optimize+ only

首先需要了解c#代码编译的过程,如下图:

C#编译器优化那点事


图片来自

C# compiler将C#代码生成IL代码的就是所谓的编译器优化。先说重点。
.NET的JIT机制,主要优化在JIT中完成,编译器optimize只做一点简单的工作。(划重点)

探究一下到底干了点啥吧,以下是使用到的工具。

Tools:
Visual studio 2017 community targeting .net core 2.0
IL DASM(vs自带)

使用IL DASM可以查看编译器生成的IL代码,这样就能看到优化的作用了。IL代码的用途与机制不是本文的重点,不明白的同学可以先去看看《C# via CLR》(好书推荐)。

按照优化的类型进行了简单的分类。

从未使用变量 代码如下:

using System; using System.Threading.Tasks; namespace CompileOpt { class Program { static void Main(string[] args) { int x = 3; Console.WriteLine("sg"); } } }

未优化的时候

.method private hidebysig static void Main(string[] args) cil managed { .entrypoint // 代码大小 15 (0xf) .maxstack 1 .locals init (int32 V_0) IL_0000: nop IL_0001: ldc.i4.3 IL_0002: stloc.0 IL_0003: ldstr "sg" IL_0008: call void [System.Console]System.Console::WriteLine(string) IL_000d: nop IL_000e: ret } // end of method Program::Main

使用优化开关优化之后:

.method private hidebysig static void Main(string[] args) cil managed { .entrypoint // 代码大小 11 (0xb) .maxstack 8 IL_0000: ldstr "sg" IL_0005: call void [System.Console]System.Console::WriteLine(string) IL_000a: ret } // end of method Program::Main

.locals init (int32 V_0)消失了(局部变量,类型为int32)
ldc.i4.3(将3推送到堆栈上)和stloc.0(将值从堆栈弹出到局部变量 0)也消失了。
所以,整个没有使用的变量,在设置为优化的时候,就直接消失了,就像从来没有写过一样。

空try catch语句 代码如下:

using System; using System.Threading.Tasks; namespace CompileOpt { class Program { static void Main(string[] args) { try { } catch (Exception) { Console.WriteLine(DateTime.Now); } try { } catch (Exception) { Console.WriteLine(DateTime.Now); } finally { Console.WriteLine(DateTime.Now); } } } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwwjdp.html