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();
}
至少在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#为您提供保护。