I'm in a situation where I have to work with linq expressions and I need to get the last bit of performance out of them. After much work, and implementing all the lower hanging fruit, I've reached a point where micro-optimizations are necessary.
Situation
interface IThing { void DoThing(); }
class A : IThing { ... } // implicitly implements IThing
Common use, interface field
// First put an instance into a IThing field
IThing x = new A();
// Then, in a different method:
x.DoThing();
This is commonly known to create an expensive interface call.
Optimized, explicit type
A x = new A();
// Then, in a different method:
x.DoThing();
This time DoThing
can be called directly since the concrete type of x
is always known (maybe A needs (or maybe it helps even more) to be sealed, not sure)
My Problem
Now, keeping the above in mind, I now want to do the same with System.Linq.Expressions
.
I'm using Expression.Constant()
right now to "capture" an IThing
into my expression tree (which I later put into a Expression.Lambda and compile), and then call a method on it.
All works fine, but I'm not sure if there's a interface dispatch happening in the compiled code. If there is, I'd really like to get rid of it because I've had great success with this optimization in the past. That is, replacing interface calls in hot code paths with "normal" calls.
Questions:
- How can I ensure the call will not use an interface method lookup?
- How can I see what machine code gets compiled for the delegate? For some reason I have a hard time stepping into the delegate in the disassembly window.
- Is code generated by expression trees optimized in the same way by the JIT as normal code?
- Do I have to explicitly specify the type in the constant? Or is it automatically detected from the given object? Is there any difference?
- How does the "indirection" though the delegate affect these things? Does it maybe prevent some optimizations? Or can the jump maybe even be optimized out entirely in some situations (maybe if the delegate is in a readonly field or so?)