What's faster: expression trees or manually emitting IL
Asked Answered
S

2

13

Is there a performance difference between creating a method emitting IL directly, as opposed to building an expression tree?

Serif answered 13/5, 2013 at 20:27 Comment(5)
Since I'm sure you've tried this already, please share your results.Chirlin
We'll I'm really trying to get at, is there some fundamental difference in the way that expression trees are compiled. For example, there is a fundamental difference in how a method is executed by reflection vs. how it is executed say, when called from an expression tree or via dynamic binding. So I'm wondering if "Compiling" expression trees produces a result that is in some way meaningfully different from what IL generated by hand would produce.Serif
Try it both ways, get out a stopwatch, you'll soon know which is faster. That's the only way to know.Ankylosis
So it sounds like in effect, there is no fundamental difference between IL vs. expression trees. I thought there might possibly be some potential difference like you see when calling a method by reflection vs. calling by dynamic binding or something to that effect. But it sounds like that isn't the case.Serif
You might also want to see microsoft-roslyn-vs-codedom, reflection-emit-vs-codedom, c-sharp-4-0-expression-trees-vs-codedom, in-c-is-expression-api-better-than-reflectionShoulder
T
14

Ultimately, the expression tree's API is really just a more familiar API over relection.emit and thus they are effectively equivalent, though I do believe there are many things that you cannot do in expression trees that you can via direct reflection.emit.

Reflection.Emit is the fastest overall, but in the same way that a for loop is faster than foreach in general. There are many scenarios where you can write code that executes faster using reflection.emit than you can using the expression api, but in most cases they should come out equivalent.

Now, the expression API does lend itself to being a slightly better way of doing things for a couple of reasons.

  1. It's composable in a simpler way than using direct reflection.emit. You can take an expression tree and re-write it to add in some logic much easier than you can than with using direct IL
  2. Optimizations may be added in the future that you may not understand that would not have occurred when using direction reflection.emit.

So ultimately, I would say it's a wash. If it's really critical and you know reflection.emit quite well, you can usually take some shortcuts in IL that you won't get using the expression API, but other than that, in general usage, they should be fairly equivalent.

Tied answered 13/5, 2013 at 20:59 Comment(2)
Perfect. This gets at the heart of what I'm after, thank you.Serif
No problem, good luck in your journey into the reflection.emit and/or expression api worlds.Tied
B
15

Excellent and complex question. Prior to recently, Expression simply could not handle all scenarios - so in many cases it was a non-question. This changes with the introduction of Expression.Block etc. In most "common" cases, the Expression usage is probably more than sufficient, but I confess I do not have precise measurements, simply for the reason that while I do lots of IL, I also target down-level frameworks which do not have luxuries like Expression (and certainly not Expression.Block). I also tend to use complex "decorator" approaches that lend themselves nicely to stack gymnastics in IL, but not necessarily into Expression (indeed, if your IL is atypical enough that reflector et al struggle with it, then it probably also doesn't map cleanly to Expression - and my IL tends to be pretty gnarly).

Sorry, I can't give you more numeric data - key points:

  • if you have down-level framework requirements the question is moot
  • otherwise, you'd have to profile
Benedetto answered 13/5, 2013 at 20:42 Comment(0)
T
14

Ultimately, the expression tree's API is really just a more familiar API over relection.emit and thus they are effectively equivalent, though I do believe there are many things that you cannot do in expression trees that you can via direct reflection.emit.

Reflection.Emit is the fastest overall, but in the same way that a for loop is faster than foreach in general. There are many scenarios where you can write code that executes faster using reflection.emit than you can using the expression api, but in most cases they should come out equivalent.

Now, the expression API does lend itself to being a slightly better way of doing things for a couple of reasons.

  1. It's composable in a simpler way than using direct reflection.emit. You can take an expression tree and re-write it to add in some logic much easier than you can than with using direct IL
  2. Optimizations may be added in the future that you may not understand that would not have occurred when using direction reflection.emit.

So ultimately, I would say it's a wash. If it's really critical and you know reflection.emit quite well, you can usually take some shortcuts in IL that you won't get using the expression API, but other than that, in general usage, they should be fairly equivalent.

Tied answered 13/5, 2013 at 20:59 Comment(2)
Perfect. This gets at the heart of what I'm after, thank you.Serif
No problem, good luck in your journey into the reflection.emit and/or expression api worlds.Tied

© 2022 - 2024 — McMap. All rights reserved.