How+=比普通表达式更优化

本文关键字:表达式 优化 How+ | 更新日期: 2023-09-27 18:00:37

我在某处读到:

良好实践:exp += val不良做法:exp = exp + val

第二个选项强制JIT评估exp的两个副本,很多时候这是不需要的。第一条语句可以比第二条语句优化得更好,因为JIT可以避免对exp求值两次。

所以我写了一个样本测试来验证这一点。但我得到了一个结果,我可以得出一些结论。有人能帮助我理解上面的做法是好是坏,或者我的例子中有任何错误吗。

        static void Main(string[] args)
    {
        DateTime startTime;
        DateTime endTime;
        for (int run = 0; run < 10; run++)
        {
            Console.WriteLine("--- Run #" + run.ToString());
            long sumB = 0;
            startTime = DateTime.Now;
            for (long i = 0; i < 1000000000; i++)
            {
                sumB = sumB + 2L;
            }
            endTime = DateTime.Now;
            Console.WriteLine(endTime - startTime);
            long sumA = 0;
            startTime = DateTime.Now;
            for (long j = 0; j < 1000000000; j++)
            {
                sumA += 2L;
            }
            endTime = DateTime.Now;
            Console.WriteLine(endTime - startTime);
        }
        Console.WriteLine("*");
        Console.ReadKey();
    }

How+=比普通表达式更优化

至少在C++中(我不知道C#),a += b只会对a求值一次,而a = a + b会对其求值两次。

如果它是一个复杂的表达式,那么它可能会对性能产生影响。如果像你的例子一样,它是一个简单的变量(或者,更一般地说,编译器可以证明的表达式没有副作用),那么两者都应该进行优化,以生成相同的代码,所以可能没有显著的差异。

更好的建议是支持a += b,因为它避免了冗余,有助于可读性,并减少了错误的范围,而不是使用(通常是虚假的或无关的)关于性能的参数。

a += b

只对每个表达式求值一次

a = a + b

对进行两次求值。a可能是一个昂贵的表达式(而不是局部变量):

int[] GetArray() { return new int[100000]; }
GetArray()[0] += 1;

与非常不同

GetArray()[0] = GetArray()[0] + 1;

在这种情况下,语义不同,但这不是重点。假设GetArray很贵。


不过,这是一种罕见的情况,我之所以这么说,是因为你问了关于性能的问题。通常情况下,你写复合作业形式纯粹是出于文体学的主观原因。


为了好玩,我们可以看看这个数组示例是如何工作的。C#编译器将发出IL,该IL计算到给定数组元素的托管指针("内部指针"),然后它将评估右侧,即它使用指针将结果存储到数组中。

令人惊讶的是,在IL级别,托管指针很常见。C#为您提供保护。