C#编译器优化

beb*_*ebo 3 c# optimization compiler-optimization

为什么编译器会优化我的代码?

我有2个功能:

public void x1() {
  x++;
  x++;
}
public void x2() {
  x += 2;
}
public void x3() {
  x = x + 2;
}
public void y3() {
  x = x * x + x * x;
}
Run Code Online (Sandbox Code Playgroud)

这是我在发布模式下编译后可以看到的ILSpy:

// test1.Something
public void x1()
{
    this.x++;
    this.x++;
}

// test1.Something
public void x2()
{
    this.x += 2;
}
// test1.Something
public void x3()
{ 
    this.x += 2;
}
// test1.Something
public void y3()
{
    this.x = this.x * this.x + this.x * this.x;
}
Run Code Online (Sandbox Code Playgroud)

x2和x3可能没问题.但是为什么x1没有针对相同的结果进行优化?没有理由保持两步增量?为什么y3不是x=2*(x*x)?那不应该快x*x+x*x吗?

这导致了这个问题?如果没有这么简单的事情,C#编译器会进行什么样的优化?

当我阅读有关编写您经常听到的代码的文章时,将其写为可读,编译器将完成其余的工作.但在这种情况下,编译器几乎什么也没做.


再添一个例子:

public void x1() {
  int a = 1;
  int b = 1;
  int c = 1;
  x = a + b + c;
}
Run Code Online (Sandbox Code Playgroud)

并使用ILSpy:

// test1.Something
public void x1()
{
    int a = 1;
    int b = 1;
    int c = 1;
    this.x = a + b + c;
}
Run Code Online (Sandbox Code Playgroud)

为什么不是这个.= 3?

das*_*ght 6

如果不假设变量x不会与运行方法同时访问,则编译器无法执行此优化.否则,可能会以可检测的方式更改方法的行为.

考虑this从两个线程同时访问引用的对象的情况.胎面A反复设定x为零; 线程B反复调用x1().

如果编译器优化x1为的等效x2,两个观察的状态x后,您的实验将是02:

  • 如果A完成之前B,你得到2
  • 如果B完成之前A,你得到0

如果在中间A先发制人B,你仍然会得到一个2.

然而,最初的版本中x1允许三种结果:x最终会成为0,12.

  • 如果A完成之前B,你得到2
  • 如果B完成之前A,你得到0
  • 如果B在第一个增量之后被抢占,那么A结束,然后B运行完成,你得到1.