Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# reflection
Hey,
 
I'm writing nowadays a custom entity framework, in which my entities define their own data members marked by custom attributes.
 
My entities inherit an abstract base class which knows to gather information using reflection about the properties during run-time (instead of having to deal with annoying abstract functions that would yield them for every entity type...), the properties can of course be cached statically, so that overhead is avoided.
 
Still, The most expensive price I have to pay is when setting and getting values from an object. I would like to minimize that. I've already tried several approaches, (PropertyInfo, Reflection.Emit, Fasterflect...), have seen some benchmark results, etc. However, as this is a rather low-level in my framework, and it doesn't expose any interfaces, I would prefer it would be as fast as possible even if the code will not be as pretty...
 
Thanks Smile | :)
Posted 22-Jan-13 5:41am
Comments
Sergey Alexandrovich Kryukov at 22-Jan-13 11:43am
   
I must say, this is an interesting question touching a very important problem. I voted 5 for the question (which happens very, very rarely, by the way).
I really hope my answer could be useful; it is based on real experience, really observing dramatic performance boost.
 
—SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

Ultimately, Reflection.Emit is the best way to go. If you found that it is unsuitable, you probably missed something. I don't know what exactly you are trying to achieve, so just some hints:
 
You don't have to create a whole separate assembly with Emit. You may choose to create separate methods. You can use System.Reflection.Emit.DynamicMethod, http://msdn.microsoft.com/en-us/library/system.reflection.emit.dynamicmethod.aspx[^].
 
You can combine Emit with caching the results. Consider this highly simplified scenario:
 
Why would you need to pass some types through Reflection at all? Only because you need to create some processing of these types and their instances, agnostic to those types, in advance. You take some types, process them with Reflection, and create some reflected artifacts in memory. If could be a set of DynamicMethod instances, or, better, delegate instances based on such methods, and some other information you dig out with Reflection: names, base types, etc.
 
Create a class to store all the results of such Reflection and Emit, call if, say, ReflectionCache.
 
All you need is to do it all once, not repeatedly. So, you need to create some dictionary indexed with some key. You can use System.Type as the key. Use, for example, System.Collections.Generic.Dictionary<System.Type,ReflectionCache>.
 
Each time you need to work with some type, you first looks for reflection cache in the dictionary. It if is found, use it: invoke delegate instanced obtained from DynamicType instances your emitted before, and so on. If the type is not found (remember, the type is the key), do extra Reflection and Emit. This way, you reach the goal: doing Reflection and Emit only once.
 
—SA
  Permalink  
v2
Comments
Marcus Kramer at 22-Jan-13 13:42pm
   
+5. Excellent.
Sergey Alexandrovich Kryukov at 22-Jan-13 13:57pm
   
Thank you very much, Marcus.
—SA
ShacharK at 22-Jan-13 17:09pm
   
It is indeed an excellent answer. Your insights were very helpful, I thank you very much for that.
Sergey Alexandrovich Kryukov at 22-Jan-13 17:13pm
   
My pleasure. And thank you, too — for this interesting question.
Good luck, call again.
—SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

There are some useful suggestions in the answer to this post ...http://stackoverflow.com/questions/771524/how-slow-is-reflection[^]
  Permalink  
Comments
PIEBALDconsult at 22-Jan-13 11:12am
   
As long as you're doing all the Reflection up front, caching the xxxInfo for each, and maintain arrays for passing the parameters, I have no other ideas.
Sergey Alexandrovich Kryukov at 22-Jan-13 11:38am
   
Exactly! Such caching is the key: after all, the goal is doing Reflection and Emit only once per type. The mechanism just should be agnostic to some set of types.
 
I tried to explain it and provided some advice in my answer, please see.
—SA
Sergey Alexandrovich Kryukov at 22-Jan-13 11:41am
   
I did not vote for this answer, because the discussion does not give definitive advice, and some of the answers are not very qualified. Please look at my answer: it is based on my positive experience.
—SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

Simply caching PropertyInfo (or FieldInfo etc) objects in a hashtable of string -> property was fast enough for quite a reflection-heavy problem for me.
  Permalink  
Comments
Sergey Alexandrovich Kryukov at 22-Jan-13 11:39am
   
Very basically, the idea is right, but the gain in performance is actually very low. I tried it and found it does not pay off. In contrast, some deeper approach come out great. It's harder to achieve though, but pay off is just great.
 
Please see my answer.
—SA
BobJanova at 22-Jan-13 11:47am
   
The gain was significant for me. What I was doing was populating a data table from a data object through reflection (because the data object could be of different types), and the time to look up the properties (through GetFields) was a lot more than the time to read all the values and populate the grid. Caching the FieldInfo objects made the UI refresh go from painful to not noticable.
 
Using Reflection.Emit is another step down the same road: a larger performance gain but more obfuscation and complication in the mechanism.
Sergey Alexandrovich Kryukov at 22-Jan-13 11:51am
   
I agree with your. The gain is a relative thing, also, it depends...
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 Sergey Alexandrovich Kryukov 8,478
1 OriginalGriff 6,516
2 Peter Leow 3,587
3 Zoltán Zörgő 3,406
4 Richard MacCutchan 2,397


Advertise | Privacy | Mobile
Web02 | 2.8.150123.1 | Last Updated 22 Jan 2013
Copyright © CodeProject, 1999-2015
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100