【问题标题】:Does initialization of local variable with null impacts performance?使用 null 初始化局部变量会影响性能吗?
【发布时间】:2011-06-12 16:47:16
【问题描述】:

让我们比较两段代码:

String str = null;
//Possibly do something...
str = "Test";
Console.WriteLine(str);

String str;
//Possibly do something...
str = "Test";
Console.WriteLine(str);

我一直认为这些代码是平等的。但是在我构建了这些代码(已检查优化的发布模式)并比较了生成的 IL 方法后,我注意到第一个示例中还有两个 IL 指令:

第一个示例代码 IL:

.maxstack 1
.locals init ([0] string str)
IL_0000: ldnull
IL_0001:stloc.0
IL_0002: ldstr "测试"
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009:调用 void [mscorlib]System.Console::WriteLine(string)
IL_000e:返回

第二个示例代码 IL:

.maxstack 1
.locals init ([0] string str)
IL_0000: ldstr "测试"
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007:调用 void [mscorlib]System.Console::WriteLine(string)
IL_000c:返回

可能这段代码是由 JIT 编译器优化的吗? 那么用null初始化局部bethod变量是否会影响性能(我知道这是非常简单的操作,但无论如何)我们应该避免它吗? 先谢谢了。

【问题讨论】:

  • 通常认为用一个永远不会使用的值进行初始化是不好的形式,仅仅是因为它增加了混乱(分配了一个对逻辑没有意义的“null”。)任何相关的性能命中可以忽略不计;前一个原因是避免它的更有说服力的原因。
  • @Dan Bryany:感谢您的评论。我同意你的观点,我们不应该使用 null 进行初始化,但一些开发人员更喜欢使用它来直接显示初始化。我的团队中有这样的人:)
  • 通常我宁愿在变量被初始化之前甚至不声明变量,因为这进一步限制了尝试理解代码时的概念范围(即本地变量尽可能地位于它们被使用的地方。 ) 这种方法的副作用是,随着方法的增长,局部变量的放置倾向于突出代码中可以提取新方法的区域。
  • @Jason:这不是一个很好的例子 - 'line' 绝对可以在循环体内限定范围。
  • @Andrew Medico:你太客气了,这是一个糟糕的例子,这显然是我的迟钝。这是一个更好的例子:string value; if(!dictionary.TryGetValue(key, out value)) { // something }.

标签: c# performance initialization jit il


【解决方案1】:

http://www.codinghorror.com/blog/2005/07/for-best-results-dont-initialize-variables.html

从文章中总结,在运行各种基准测试后,将对象初始化为一个值(作为定义的一部分、在类的构造函数中或作为初始化方法的一部分)大约在 10-35 之间在 .NET 1.1 和 2.0 上慢 %。较新的编译器可能会优化定义时的初始化。文章最后建议作为一般规则避免初始化。

【讨论】:

【解决方案2】:

正如 Jon.Stromer.Galley 的链接所指出的那样,它会稍微慢一些。但是差异非常小。可能在 纳秒 的数量级上。在那个级别上,使用像 C# 这样的高级语言的开销使任何性能差异都相形见绌。如果性能是一个很大的问题,那么您还不如使用 C 或 ASM 或其他方式进行编码。

在成本与收益方面,编写清晰代码(无论这对您意味着什么)的价值将远远超过 0.00001 毫秒的性能提升。这就是 C# 和其他高级语言首先存在的原因。

我知道这可能是一个学术问题,我并不低估了解 CLR 内部结构的价值。但在这种情况下,这似乎是一个错误的关注点。

【讨论】:

    【解决方案3】:

    今天(2019 年).NET Framework 和 .NET Core 编译器都足够智能,可以优化不需要的初始化。 (以及无用的stloc.0 - ldloc.0 对。)

    两个版本都编译为

            .maxstack 8
    
            ldstr "Test"
            call void [System.Console]System.Console::WriteLine(string)
            ret
    

    请参阅我的SharpLab experiment 作为参考。

    当然实现会发生变化,但贾斯汀的回答是永恒的:我出于好奇进行了这个实验,在真实情况下专注于代码的清晰度和表现力,而忽略了微优化。

    【讨论】:

      猜你喜欢
      • 2016-03-30
      • 1970-01-01
      • 1970-01-01
      • 2021-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-17
      相关资源
      最近更新 更多