LmT*_*oon 9 c# clr compiler-optimization
假设我有以下程序:
static void SomeMethod(Func<int, int> otherMethod)
{
otherMethod(1);
}
static int OtherMethod(int x)
{
return x;
}
static void Main(string[] args)
{
SomeMethod(OtherMethod);
SomeMethod(x => OtherMethod(x));
SomeMethod(x => OtherMethod(x));
}
Run Code Online (Sandbox Code Playgroud)
我无法理解编译的il代码(它使用了额外的代码).这是简化版:
class C
{
public static C c;
public static Func<int, int> foo;
public static Func<int, int> foo1;
static C()
{
c = new C();
}
C(){}
public int b(int x)
{
return OtherMethod(x);
}
public int b1(int x)
{
return OtherMethod(x);
}
}
static void Main()
{
SomeMethod(new Func<int, int>(OtherMethod));
if (C.foo != null)
SomeMethod(C.foo)
else
{
C.foo = new Func<int, int>(c, C.b)
SomeMethod(C.foo);
}
if (C.foo1 != null)
SomeMethod(C.foo1)
else
{
C.foo1 = new Func<int, int>(c, C.b1)
SomeMethod(C.foo1);
}
}
Run Code Online (Sandbox Code Playgroud)
为什么编译器不是创建静态相等的方法b/b1
?等于意味着它们具有相同的代码
Eri*_*ert 18
你的问题是:为什么编译器没有意识到这两行
SomeMethod(x => OtherMethod(x));
SomeMethod(x => OtherMethod(x));
Run Code Online (Sandbox Code Playgroud)
是相同的,写这个
if ( delegate is not created )
create the delegate and stash it away
SomeMethod( the delegate );
SomeMethod( the delegate );
Run Code Online (Sandbox Code Playgroud)
?让我以几种方式回答这个问题.
首先,允许编译器进行优化吗?是.该规范要求允许 C#编译器将两个lambdas做成完全相同的事情到一个委托中.实际上你可以看到它已经部分地进行了这种优化:它创建了每个委托一次并将其保存起来,以便以后再次调用代码时不必再创建它.请注意,在仅调用一次代码的情况下,这会浪费内存.
第二,编译器是否需要进行缓存优化?不是.规范要求编译器只允许进行优化,但不是必需的.
编译器是否需要进行所需的优化?显然不是,因为它没有.它是允许的,也许是编译器的未来版本.编译器是开源的; 如果您关心此优化,请编写并提交拉取请求.
第三,是否可以进行所需的优化?是.编译器可以获取出现在同一方法中的所有lambda对,将它们编译为内部树格式,并进行树比较以查看它们是否具有相同的内容,然后为两者生成相同的静态后备字段.
所以现在我们有一种情况:允许编译器进行特定的优化,但事实并非如此.你问过"为什么不"?这是一个容易回答的问题:所有优化都没有实施,直到有人花费大量时间和精力:
您想要的优化根本不符合标准.没有人写这样的代码.如果他们这样做了,并且他们关心它复制了一个对象,他们可以轻松地自行修复它.因此,优化优化了不存在的代码,以获得"胜利",即在程序将分配的数百万个对象中构建单个对象.不值得.
但是,如果您认为是这样,请继续执行并提交拉取请求.请务必提交我上面提到的调查结果,因为这些是实际工作的地方.实施通常是花在功能上的总工作量的最小部分; 这就是为什么C#是一种成功的语言.
归档时间: |
|
查看次数: |
445 次 |
最近记录: |