Is there a performance difference between creating a method emitting IL directly, as opposed to building an expression tree?
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.
- 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
- 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.
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
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.
- 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
- 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.
© 2022 - 2024 — McMap. All rights reserved.