EX pression树木性能树木、性能、EX、pression

2023-09-03 05:41:08 作者:无尘尊者

我目前的理解是,硬codeD'code是这样的:

My current understanding is that 'hard coded' code like this:

public int Add(int x, int y) {return x + y;}

会总是这样的表现比前pression树code更好的:

will always perform better than expression tree code like this:

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);

因为编译器有更多的信息,并可以将更多的精力放在优化code,如果你在编译时编译。这通常是真的吗?

as the compiler has more information and can spend more effort on optimizing the code if you compile it at compile time. Is this generally true?

推荐答案

编辑

防爆pression.Compile 呼叫经过进程如出一辙任何其他.NET code应用程序包含在这个意义上说:

The call to Expression.Compile goes through exactly the same process as any other .NET code your application contains in the sense that:

在产生IL code 在IL code是JIT,特德机code

(解析步骤被跳过,因为将要从输入code产生的实施例pression树已经创建并且不具有)

(the parsing step is skipped because an Expression Tree is already created and does not have to be generated from the input code)

您可以看看source code前pression编译验证确实产生IL code。

You can look at the source code of the expression compiler to verify that indeed, IL code is generated.

优化

请注意,几乎所有由CLR执行的优化是在JIT步骤中完成,而不是从编译C#源$ C ​​$ C。从您的lambda的委托编制IL code时,机器code这种优化也将完成。

Please be aware that almost all of the optimization done by the CLR is done in the JIT step, not from compiling C# source code. This optimization will also be done when compiling the IL code from your lambda delegate to machine code.

您的例子

在你的榜样,你是在比较苹果与梨。第一个例子是一个方法定义,第二个例子是运行时间code表示创建一个方法,编译和执行它。它需要创建/编译的方法中的时间比实际执行它多少要长得多。但是,您可以创建后保持编译的方法的一个实例。当你这样做,你的生成方法的性能应该是相同的,原来的C#方法。

In your example you are comparing apples with pears. The first example is a method definition, the second example is runtime code that creates a method, compiles and executes it. The time it takes to create/compile the method is much much longer than actually executing it. However you can keep an instance of the compiled method after creation. When you have done that, the performance of your generated method should be identical to that of the original C# method.

考虑这种情况下:

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);

所以,人们可能会得出这样的结论是:IL code是IL code,不管它是如何产生的,和LINQ防爆pressions产生IL code

So the conclusion one might draw is: IL code is IL code, no matter how it is generated, and Linq Expressions generate IL code.