为什么C#编译器要为每个传递的委托创建一个新的Action实例? [英] Why does the C# compiler create a new Action instance for every passed delegate?

查看:0
本文介绍了为什么C#编译器要为每个传递的委托创建一个新的Action实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码:

public static void M() {
    A(V);
    A(V);
    A(V);
}

public static void V() {

}

public static void A(Action x) {
    x();   
}

这将在后台编译为:

public static void M() {
    A(new Action(V));
    A(new Action(V));
    A(new Action(V));
}

但是,我们可以编写自己的简单性能改进来减少不必要的垃圾:

private static readonly Action v = new Action(V);
A(v);
A(v);
A(v);

对于这个非常简单的情况,Roslyn为什么不能进行类似的优化?

如果答案是否定的,那么当方法不是静态的而是实例成员时呢?如果捕获了关闭变量,该怎么办?

推荐答案

我们可以编写自己的简单性能改进来减少不必要的垃圾

您重新发现了公共子表达式消除的一个特例--确定两个或更多表达式何时具有完全相同的值、计算一次值并将其存储在变量中以供重复使用的优化。

在继续之前,我要提醒您,所有所谓的"优化"实际上都是在用一件事换另一件事。您提出的优化以每次调用产生的少量收集压力为代价,而不是以少量内存泄漏为代价。静态字段中的缓存值将成为第二代堆的永久成员。这值得吗?这是一个你想要通过实际测量来回答的问题。

对于这个非常简单的情况,Roslyn为什么不能进行类似的优化?

如果优化没有在程序的行为中产生不可接受的更改,则原则上没有原因无法执行此优化

具体地说,优化会导致两个先前值相等但不是引用相等的委托变为引用相等。这可能是可以接受的。

在实践中,实现优化需要在设计、实现、测试和维护执行优化的代码方面付出大量努力。C#不实现公共子表达式消除优化。这种优化的性价比很低。很少有人编写将从优化中受益的代码,而且优化很小,而且,正如您所发现的那样,如果您关心的话,"手动"进行优化是很容易的。

我注意到,C#确实在lambdas上进行了类似的缓存。它不会执行公共子表达式消除,但只会生成一次特定的lambdas并缓存结果:

void M() { Action x = () => {}; ... }

将生成,就像您写下:

static Action anon = null;
void M() 
{
  if (anon == null) anon = () => {};
  Action x = anon;
  ...

如果答案是否定的,那么当方法不是静态的而是实例成员时怎么办?

如果优化没有在程序的行为中产生不可接受的更改,则原则上没有原因无法执行此优化

我注意到,在这种情况下,需要进行优化来推断实例当然是相同的。如果不这样做,将无法保持程序行为不能更改的不变性。

同样,在实践中,C#不执行公共子表达式消除。

如果捕获了关闭变量怎么办?

被什么捕获?您刚才谈到了方法组转换为委托,显然现在我们谈论的是转换为委托的lambda。

C#规范明确规定,编译器可以选择在相同的lambdas上执行公共子表达式消除,也可以不选择,视情况而定。

如果优化没有在程序的行为中产生不可接受的更改,则原则上没有不能执行此优化的理由。由于规范明确指出允许此优化,因此根据定义它是可接受的。

同样,在实践中,C#不执行公共子表达式消除。

也许您注意到了这里的一种趋势。问题的答案是"允许这样或那样的优化吗?"答案几乎总是"是的,如果它不会给项目的行为带来不可接受的变化"。但问题的答案是"C#在实践中实现这样或那样的优化了吗?"通常为否。

如果您想了解编译器执行的优化的一些背景知识,请访问I described them in 2009

在大多数情况下,Roslyn在这些优化方面做得更好。例如,Roslyn在将临时值和本地变量具体化为短暂变量而不是持久变量方面做得更好。我完全重写了可为空的算术优化器;my eight-part series of articles describing how is here。还有更多的改进。不过,我们从未考虑过进行CSE。

这篇关于为什么C#编译器要为每个传递的委托创建一个新的Action实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆