wh1*_*t1k 7 c# random performance delegates inline
假设我已经编写了这样一个类(函数的数量并不重要,但实际上,将会有大约3或4个).
private class ReallyWeird
{
int y;
Func<double, double> f1;
Func<double, double> f2;
Func<double, double> f3;
public ReallyWeird()
{
this.y = 10;
this.f1 = (x => 25 * x + y);
this.f2 = (x => f1(x) + y * f1(x));
this.f3 = (x => Math.Log(f2(x) + f1(x)));
}
public double CalculusMaster(double x)
{
return f3(x) + f2(x);
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道C#编译器是否可以优化这样的代码,以便它不会经历多次堆栈调用.
是否能够在编译时内联代理?如果是,在哪些条件和哪些限制?如果不是,有答案为什么?
另一个问题,甚至可能更重要:它会比我声明f1, f2 and f3的方法慢得多吗?
我问这个是因为我想尽可能保持我的代码为DRY,所以我想实现一个扩展基本随机数生成器(RNG)功能的静态类:它的方法接受一个委托(例如来自NextInt()RNG的方法)并返回另一个Func代表(例如用于生成ulongs),建立在前者之上.只要有许多不同的RNG可以产生ints,我宁愿不考虑在不同的地方实施十次相同的扩展功能.
因此,可以多次执行该操作(即,类的初始方法可以由代表"包裹"两次或甚至三次).我想知道性能开销会是什么样的.
谢谢!
如果您使用表达式树而不是完整的 Func<>,编译器将能够优化表达式。
编辑为了澄清,请注意,我并不是说运行时会优化表达式树本身(它不应该),而是因为生成的Expression<>树是.Compile()一步完成的,JIT 引擎将简单地看到重复的子表达式并能够优化、整合、替代、捷径以及它通常所做的其他事情。
(我不确定它在所有平台上都适用,但至少它应该能够充分利用 JIT 引擎)
评论回复
首先,表达式树的执行速度可能与 Func<> 相同(但是 Func<> 不会具有相同的运行时成本 - JITting 可能会在 jitting 封闭范围时发生;在 ngen 的情况下,它甚至会是 AOT,与表达式树相反)
第二:我同意表达式树可能很难使用。请参阅此处,了解如何编写表达式的著名简单示例。然而,更复杂的例子很难得到。如果我有时间,我会看看是否可以提出一个 PoC,并看看 MS.Net 和 MONO 在这些情况下在 MSIL 中实际生成了什么。
第三:不要忘记Henk Holterman说这是不成熟的优化可能是正确的(尽管提前撰写Expression<>而不是Func<>提前只是增加了灵活性)
最后,当您真正考虑推动这一目标时,您可能会考虑使用编译器即服务(Mono 已经有了,我相信 Microsoft 仍然会推出它?)。