【问题标题】:Why doesn't C# compiler optimize away duplicate local variable default value initialization?为什么 C# 编译器不优化重复的局部变量默认值初始化?
【发布时间】:2013-06-24 13:51:59
【问题描述】:

背景

我知道编译器会“省略为字段生成 int foo = 0; 之类的代码,因为内存分配器会将字段初始化为默认值。” Reference

        class Foo
        {
            public int a = 1;
            public int b = 0;
        }
        Foo..ctor:
        IL_0000:  ldarg.0     
        IL_0001:  ldc.i4.1
        IL_0002:  stfld       UserQuery+Foo.a // There is no b.
        IL_0007:  ldarg.0
        IL_0008:  call        System.Object..ctor
        IL_000D:  ret

我还知道“编译器会在每个使用局部变量的方法上自动添加.locals init,这表明 JIT 必须在开始执行方法之前注入初始化所有局部变量的代码。” Reference

问题

为什么编译器不为 int foo = 0; 之类的局部变量生成 IL,因为 .locals init 已经涵盖了这一点? (为了与字段保持一致?)

(我知道 C# 规范要求明确分配局部变量,我同意。)

(我引用的链接说明了为什么需要.locals init,以及为什么C#规范需要初始化locals。但没有说明为什么必须存在额外的IL指令来初始化默认值。作为验证过程已被.locals init 保证)

void Main()
{
    int a = 0;
    int b = 1;
    int c = 0;
    int d = a + b + c;
    d++;
}

.maxstack 2
.locals init (int a, int b, int c, int d)

IL_0000:  ldc.i4.0    
IL_0001:  stloc.0     // a (Can be optimized away)
IL_0002:  ldc.i4.1    
IL_0003:  stloc.1     // b
IL_0004:  ldc.i4.0    
IL_0005:  stloc.2     // c (Can be optimized away)
IL_0006:  ldloc.0     // a
IL_0007:  ldloc.1     // b
IL_0008:  add         
IL_0009:  ldloc.2     // c
IL_000A:  add         
IL_000B:  stloc.3     // d
IL_000C:  ldloc.3     // d
IL_000D:  ldc.i4.1    
IL_000E:  add         
IL_000F:  stloc.3     // d

【问题讨论】:

  • .locals init 是否涵盖此案例?这些是成员变量而不是局部变量,因此处理方式不同?
  • 好的,既然你已经阐明了这个例子,我明白你的意思了。
  • 好像stackoverflow.com/a/3383168/56778 回答了这个问题。
  • 如果我猜我会说它与变量的碳足迹有关,那么当方法完成执行时它无论如何都会被 gc'd,该类必须使用 idisposable跨度>
  • @JimMischel 我不认为stackoverflow.com/questions/753438/… 会回答。它说明了.locals init 必不可少的原因,以及 C# 规范要求初始化本地变量的原因。但它没有说明为什么必须存在额外的 IL 指令。 (因为验证过程由.locals init 保证)

标签: c# clr il


【解决方案1】:

为什么编译器不为 int foo = 0; 之类的局部变量生成 IL,因为 .locals init 已经涵盖了这一点?

为什么要这样做?我还没有实际验证这一点,但是如果您删除了不必要的初始化,JIT 编译器会生成不同的本机代码,我会感到惊讶。

这意味着将这种优化添加到 C# 编译器的唯一好处是使 JIT 编译稍微快一点(因为它必须处理更少量的 IL 代码)。似乎 C# 编译器的作者为了如此微小的好处而进行这种优化是不值得的。

【讨论】:

  • 我知道局部变量情况下没有性能差异。但是在现场情况下也没有区别。他们确实对字段进行了优化,为什么不对变量做同样的事情呢?
  • @colinfang 我认为“生成一致的 IL”在 C# 团队的优先事项列表中非常低。
  • 它可能希望这样做以优化 IL 大小并减少在 JIT 中花费的时间。不过,它可能在列表中还不够高。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-25
  • 1970-01-01
  • 2015-05-13
  • 2016-04-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多