cs0*_*815 23 .net c# performance expression-trees
我目前的理解是这样的'硬编码'代码:
public int Add(int x, int y) {return x + y;}
Run Code Online (Sandbox Code Playgroud)
将始终比表达式树代码执行更好,如下所示:
Expression<Func<int, int, int>> add = (x, y) => x + y;
var result = add.Compile()(2, 3);
var x = Expression.Parameter(typeof(int));
var y = Expression.Parameter(typeof(int));
return (Expression.Lambda(Expression.Add(x, y), x, y).
Compile() as Func<int, int, int>)(2, 3);
Run Code Online (Sandbox Code Playgroud)
因为编译器有更多信息,如果在编译时编译它,可以花更多精力优化代码.这一般是正确的吗?
Bas*_*Bas 20
汇编
调用与Expression.Compile您的应用程序包含的任何其他.NET代码完全相同的过程在以下意义上:
(跳过解析步骤,因为已经创建了表达式树,不必从输入代码生成)
您可以查看表达式编译器的源代码,以验证是否确实生成了IL代码.
优化
请注意,CLR完成的几乎所有优化都是在JIT步骤中完成的,而不是编译C#源代码.在将lambda委托中的IL代码编译为机器代码时,也会进行此优化.
你的榜样
在您的示例中,您正在比较苹果和橙子.第一个示例是方法定义,第二个示例是创建方法,编译和执行它的运行时代码.创建/编译方法所花费的时间比实际执行它要长得多.但是,您可以在创建后保留已编译方法的实例.完成后,生成的方法的性能应与原始C#方法的性能相同.
考虑这种情况:
private static int AddMethod(int a, int b)
{
return a + b;
}
Func<int, int, int> add1 = (a, b) => a + b;
Func<int, int, int> add2 = AddMethod;
var x = Expression.Parameter(typeof (int));
var y = Expression.Parameter(typeof (int));
var additionExpr = Expression.Add(x, y);
Func<int, int, int> add3 =
Expression.Lambda<Func<int, int, int>>(
additionExpr, x, y).Compile();
//the above steps cost a lot of time, relatively.
//performance of these three should be identical
add1(1, 2);
add2(1, 2);
add3(1, 2);
Run Code Online (Sandbox Code Playgroud)
因此,可能得出的结论是:IL代码是IL代码,无论它是如何生成的,Linq表达式生成IL代码.
您的Add函数可能编译为某些函数开销(如果没有内联)和单个add指令.没有比这更快.
即使构造这个表达式树也会慢一个数量级.与直接C#实现相比,为每次调用编译新函数将非常昂贵.
尝试只编译一次该函数并将其存储在某处.
| 归档时间: |
|
| 查看次数: |
8140 次 |
| 最近记录: |