Steve Eichert had a good post about the true cost of reflection. Since I’ve been writing a lot of code that tries to use reflection in the most efficient manner possible, I was really interested in what he had to say. The number he reported were a bit surprising to me; I knew reflection was expensive, but I didn’t think it was as expensive as Steve’s numbers seemed to indicate.
Steve tested the cost of setting a property in the usual way versus the cost of setting the private property backer field directly via reflection. I think there are two significant problems with this test. First, the two actions are not necessarily semantically equivalent – setting the backing field directly via reflection bypasses any logic that might exist in the setter method. Secondly, it’s possible that the cost of manipulating a private member variable via reflection might be substantially higher than doing other reflection manipulations. I did a bit of research myself, and it looks as though the latter is definitely true.
I expanded the test code on Steve’s page to exercise several different ways of getting and setting values on an object. Here are the aggregate numbers (for 100000 repetitions per test run).
Public Properties
Normal property set: .01
Reflective property set: .08
Normal property set: .01
Reflective property set: .08
Public fields
Normal public field set: .01
Reflective public field set: .08
Normal public field get: .01
Reflective public field get: .08
Private fields
Normal private field set: .01
Reflective private field set: 4.8
Normal private field get: .01
Reflective private field get: 4.8
The last numbers are very similar to Steve’s original results.
It seems that reflection imposes a small-but-manageable performance overhead, so long as you are using reflection to manipulate public members. That cost increases astronomically, however, when you resort to using private reflection. Thus, not only is private reflection bad from a design point of view because is breaks abstraction, it’s terrible from a performance perspective because it’s dog slow.
The bottom line: reflection is costly, but not as costly as the original performance test seemed to indicate. Next step: figure out what's going on under the hood to make this case so slow.
The code for my tests can be found here.
[Update: In my comments, Jason Goodwin points out that CodeAccessSecurity comes into play when doing private reflection. Callers need to have ReflectionPermission to reflect on private fields. I'm less convinced than I was earlier that this is the full explanation for the performance hit. Unless ReflectionPermission is being demanded every time SetValue is being called, I would expect security to come into play (and performance to be thusly degraded) only when the FieldInfo is initially obtained. I can definitely see a design argument for enforcing security every time, but I'm not definitively convinced that's necessarily going on. I suppose I could write some code to test this hypothesis, but I'm not motivated enough to do that right now. Sigh.]
