C#编译器优化
编译器为什么要优化我的代码 我有两个功能:C#编译器优化,c#,optimization,compiler-optimization,C#,Optimization,Compiler Optimization,编译器为什么要优化我的代码 我有两个功能: public void x1() { x++; x++; } public void x2() { x += 2; } public void x3() { x = x + 2; } public void y3() { x = x * x + x * x; } 这就是我在发布模式下编译后看到的ILSpy: // test1.Something public void x1() { this.x++; this.x
public void x1() {
x++;
x++;
}
public void x2() {
x += 2;
}
public void x3() {
x = x + 2;
}
public void y3() {
x = x * x + x * x;
}
这就是我在发布模式下编译后看到的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;
}
x2和x3可能还可以。但是为什么x1没有优化到相同的结果呢?没有理由保持2步增量?
为什么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;
}
以及使用ILSpy:
// test1.Something
public void x1()
{
int a = 1;
int b = 1;
int c = 1;
this.x = a + b + c;
}
为什么不是这个.x=3?
x1
和x2
不一样:
如果x
是一个公共字段,并且是在多线程环境中访问的,那么第二个线程完全有可能在两次调用之间发生x
变异,这在x2
中的代码是不可能的
对于y2
,如果+
和/或*
为x
类型重载,则x*x+x*x
可能不同于2*x*x
编译器将优化以下内容(不是详尽的列表):
- 删除未使用的局部变量(释放寄存器)
- 删除不影响逻辑流或输出的代码李>
- 对简单方法的内联调用
嗯,编译器可能会做一些优化,但在设计时仍有很多工作可以做以提高性能。是的,可读代码确实很有价值,但编译器的工作是生成与源代码相对应的工作IL,而不是将源代码更改得更快。如果不假设变量
x
不会与正在运行的方法同时访问,编译器就无法执行此优化。否则,可能会以可检测的方式改变方法的行为
考虑这样一种情况,即从两个线程同时访问this
引用的对象。踏板A
反复将x
设置为零;线程B
反复调用x1()
如果编译器将x1
优化为与x2
等效,则在您的实验之后,x
的两个可观察状态将是0
和2
:
- 如果
在A
之前完成,您将得到B
2
- 如果
在B
之前完成,则得到A
0
如果<代码> A/COD>在中间预置<代码> B<代码>,则仍将得到<代码> 2 < /C> > < /P> 但是,原始版本的
x1
允许三种结果:x
最终可能是0
、1
或2
- 如果
在A
之前完成,您将得到B
2
- 如果
在B
之前完成,则得到A
0
- 如果
在第一次增量后被抢占,然后B
完成,然后A
运行到完成,则得到B
1
x=2*(x*x)
比x=x*x+x*x
更优化?可读性或术语的缩减并不意味着公式运算更加优化,有时扩展它意味着其更加优化。1。大多数优化在运行时由JIT编译器执行,而不是由C#编译器执行。2.对于多线程,您建议的x1
优化在功能上是不等价的(例如,如果字段是可变的,则编译器绝对不允许执行建议的优化)。这里有一篇关于C#编译器确实执行的优化的文章:代码越少并不意味着性能越好,x++是一种特殊情况,因为它涉及缓存要返回的值,然后对其进行递增。2次乘法是否不比2次乘法和一次加法快?我添加了一个与多线程无关的新示例?--顺便问一下,如果编译器可以对指令进行重新排序以优化性能,并且您需要采取诸如MemoryFences之类的特殊操作来防止这种情况发生,那么为什么组合x++和x++会有所不同呢?如果没有锁或MemoryBarrier,我希望编译器不关心多线程。我认为您对编译器的期望太高了。它的工作是将您的源代码转换为可工作的IL,而不是找到每一个可以让您的代码更快的地方并为您重新编码。如果你觉得这是下一个C#编译器的一个有价值的特性,那么就把它发布出来,看看会发生什么。另外,为什么要到此为止?为什么不将列表
更改为数组
?为什么不将您的if
语句系列更改为开关
?或者,如果条件永远不可能为真,则删除一个if
块?许多人都会抱怨编译器的速度不够快。我们问题的基本答案是:任何功能都必须经过设计、编码、测试、记录和支持,所有这些都需要花费时间和金钱,而其他许多功能都在竞争。如果这样一个特性的好处不超过成本(或者如果其他特性提供更多好处),那么它就不会被生产出来。我想这种优化的好处是微乎其微的。@bebo编译器生成IL,它甚至不尝试优化。JIT的工作是在此基础上执行依赖于平台的优化。信息技术