繁体   English   中英

C#性能的影响和操作的变化

[英]Effect of consts and variablization of operations in C# performance

常量通常用于C / C ++编程中,作为产生更清晰代码的一种方式。 有时也可能存在优化益处。 但是,我想知道除了更易读的代码之外,从C#中声明值是只读还是有效可以获得什么好处。

假设我有以下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#的良好编码实践并使代码更容易理解并且更难以犯错之外,是否有好处 - 特别是在性能方面 - 做我上面做的事情? 值是否会在本地内存中保留更长时间?

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

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

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

我想知道的是,除了作为C#的良好编码实践并使代码更容易理解并且更难以犯错之外,是否有好处 - 特别是在性能方面 - 做我上面做的事情?

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

值是否会在本地内存中保留更长时间?

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

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

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

因此,除非您遇到严重的性能问题,然后确定作为瓶颈的代码块,否则我认为从优化角度来看这些小细节并不值得担心。 在那之后,在那个集中的代码上,花一些时间进行优化是值得的。

标准警告:根据您的具体情况readonly尝试和测量不同的代码变体 - constreadonly ,字段/属性对性能有不同的影响,可能会有所不同。

常量表达式是在编译时计算的 - 所以如果所有子表达式都是常量,那么通过声明额外的常量就不会获得任何东西:

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

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

Readonly是运行时值,并且可以使用JIT内联调用,但您仍然可以获得访问字段的费用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM