Why is the PropertyInfo
methods for getting and setting a property so slow? If I build a delegate using Reflection.Emit
, it is much faster.
Are they doing something important, so that the time they take can be justified? That is... am I missing something by using Reflection.Emit
to build delegates instead of usign the GetValue
and SetValue
of the PropertyInfo (aside of development speed)?
PS: Please, give evidence, not only guessing!
The implementation of RuntimePropertyInfo
(which is the concrete subclass of PropertyInfo
for runtime types) implements GetValue
and SetValue
by invoking the getter and setter methods via reflection (MethodInfo.Invoke
), whereas your generated delegate probably calls the methods directly. Therefore, the question boils down to: why is RuntimeMethodInfo.Invoke
so slow when compared to a compiled invocation?
When you decompile (or look at the reference sources for) RuntimeMethodInfo.Invoke
, you can see that this is probably because Invoke
carries out a lot of tasks:
The runtime will perform similar consistency, security, and visibility checks when it compiles your delegate into executable native code. It also emits code for boxing/unboxing, etc. However, it only needs to do these things once, and can then guarantee that the code is safe to execute. This makes the actual method call a very cheap operation (load the parameters and jump to the method address).
In contrast, every call to RuntimeMethodInfo.Invoke
(and thus to GetValue
/SetValue
) needs to repeat all the work, since the context - parameters, instance, and usage of the return type - is not known. And this is probably why it is so slow.
About what you might be missing: if you emit your own property invocation delegates, you of course need to deal with boxing/unboxing, ref/out parameters, etc. yourself.
There is no need to use Emit. It is far more easy to use Expression. You can speed up the access as described in SO. The helper class creates a "method pointer" (Action/Func) to the getter or setter. If you reuse the Action/Func you will be able to perform as fast as a normal setter.
// creating setter (once)
var propertyInfo = typeof(T).GetProperty(field);
var setter = FastInvoke.BuildUntypedSetter<T>(propertyInfo));
// usage somehow later in a loop of data
foreach(var myobject in MySource)
{
setter(myobject, myValue)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With