【问题标题】:Effect of consts and variablization of operations in C# performanceC# 性能中操作的常量和变量化的影响
【发布时间】:2014-07-16 01:50:22
【问题描述】:

在 C/C++ 编程中经常使用常量来生成更清晰的代码。有时也可能有优化的好处。但是,我想知道除了更具可读性的代码之外,在 C# 中将值声明为只读或 const 可以收集到什么好处。

假设我有以下 C# 代码:

public Double HalfPiSomething(Int32 input)
{
    return input + (Math.PI / 2);
}

这是一个相当简单的例子,但是每次调用该方法时,我们将Math.PI 除以2,将其添加到输入中,然后将其返回到调用语句。

让我们使用该代码并在包含类的某处将Math.PI / 2 设为它自己的变量:

private Double _halfPi = Math.PI / 2;

public Double HalfPiSomething(Int32 input)
{
    return input + _halfPi;
}

显然,将Math.PI / 2 的操作放在自己的变量中是一个好主意,就像基本的编码练习一样,特别是如果该值在类中的多个点中使用...这里不在这里,但是让我们只是假装。

最后,既然_halfPi 永远不会改变,那就让它成为const

private const Double _halfPi = Math.PI / 2;

public Double HalfPiSomething(Int32 input)
{
    return input + _halfPi;
}

我想知道的是,除了作为 C# 的良好编码实践和使代码更易于理解和更难出错之外,执行上述操作是否有好处(尤其是在性能方面)?该值是否在本地内存中停留的时间更长?

【问题讨论】:

    标签: c# c++ performance optimization


    【解决方案1】:

    每次调用该方法时,我们将Math.PI除以2,添加到输入中,然后返回到调用语句。

    不,这不是正在发生的事情:C# 编译器在编译时计算常量表达式。此外,当混合常量和非常量的表达式具有可以在编译时计算的子表达式时,编译器会预先计算该值,就像它是单个常量一样。

    编译器将Math.PI / 2 子表达式识别为常量,执行计算,并生成将输入添加到预先计算的除法结果的代码。

    我想知道的是,除了作为 C# 的良好编码实践和使代码更易于理解和更难出错之外,执行上述操作是否有好处(尤其是在性能方面)?

    不,没有理由做编译器的工作,除非它导致更清晰。

    值在本地内存中的保留时间更长吗?

    常量值被“烘焙”到编译器生成的代码中。它们不是本地数据内存的一部分(尽管它们肯定在内存中,只要代码在内存中)。

    【讨论】:

      【解决方案2】:

      这些次要优化中的大部分都由编译器和 JIT 为您处理。例如,如果我编译你的第一段代码,反编译结果是

          public double HalfPiSomething(int input)
          {
              return (double)input + 1.5707963267949;
          }
      

      因此,从优化的角度来看,我认为不值得担心这些小细节,除非您遇到了严重的性能问题,然后确定了成为瓶颈的代码块。在那之后,专注于那段代码,花一些时间优化是值得的。

      【讨论】:

        【解决方案3】:

        标准警告:尝试针对您的特定情况自行测量不同的代码变体 - constreadonly,字段/属性对性能有不同的影响,并且可能会有所不同。

        常量表达式是在编译时计算的 - 因此,如果所有子表达式都是常量,则通过声明额外的常量不会获得任何收益:

        const double halfPi = Math.PI / 2;
        var r1 = halfPi * 3;    
        var r2 = Math.PI / 2 * 3;
        

        r1r2 将被初始化为完全相同的值。

        Readonly 是运行时值,调用可以使用 JIT 内联,但您仍然可以通过访问字段获得报酬。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-04-01
          • 2019-10-23
          • 1970-01-01
          • 1970-01-01
          • 2023-03-19
          • 1970-01-01
          • 2021-11-02
          相关资源
          最近更新 更多