Groups | Blog | Home
all groups > dotnet performance > february 2005 >

dotnet performance : Reflection.Cache



Questionner
2/22/2005 4:21:01 AM
I know that the Code I’ve written will sound silly to some of you, and maybe
it is. I am planning to change it.

ANYWAY ;-) I do create and Initialize *a lot* (+-5000) of object (that
not-quite incidentally, are also different classes). To do that I use
extensively reflection .GetMembers() GetMethod() GetFields().GetValue() et
etc etc

Yes it IS slow, yes I am gona use “normal” virtual properties. But how is it
possible that after this procedure and GC.Collect()’ing everything there is
still 200.000 object still present in the heap ? (MemberInfo, PropertiesInfo,
ClearCacheHanlder, and more, with 150 MB of process ram used).

After doing a bit of research with the .Net memory profiler (excellent tool
!) and Lutz Roeder’s .Net reflector (amazing tool :-) it appears to me that
there is a private Reflection.Cache object that does not provide any way to
Flush its “became useless” content.

Is it normal that the Reflection library is so careless about its memory
consumption? Can it be tweaked in some way that does not involve recompiling
Reflection to made those private lullabies public ?
Questionner
2/23/2005 1:03:02 PM
Yes, you are mostly right, and thank you for your answer. The usage of
reflection to initialize once, one object (singleton of its class) is
overkill (especially for thousand of them :-). Reflection is too slow and
probably not done for such purpose... I have already fixed that.

To clear things up: no those classes are not Emit’ed. They are pure C#
files. You can easily understand the purpose like this:
Classes and nested classes are constructed just like any (think XML) *data*
representation. They could as well be constructed with reflection.Emit, but
why bother ? the compiler handles the task much better, and to get to the
point: at code design time.
You then have nice strongly typed data/object, even
presented/browsable/commented by intellisense (just one example).

The idea is not really mine, because other designable class-instance breed
already provide this feature (namely Component(or Control) implementation
(win/web form etc etc). I just apply the theory to its full extend ;-)

Digging docs and so I found that an assembly “<=1.1” support up to16 million
classes. Some site like http://blogs.msdn.com/joelpob/ provide really nice
“insider” information…
An application (many assembly ?) with more then 10000 designable component
is not far-fetch to my point of view. I hope that I am not wrong, and that
..Net won’t give-up on me :-)

Generics of 2.0 partly solve this problem of strong typing similar
functionalities, but it also implies building new classes at run-time (even
behind the scene)…

But more to the point of this performance newsgroup, I can still not believe
that any cache whatsoever can eats up so much ram without further notice.
There ARE actually links between the GC class and
Reflection.Cache.ClearCacheHandler private thing (so said disassembler). But
all I know (or think I know ;-) is that asp_net iis process still gets
recycle (60% of physical ram limit) without trying first to flush those 130
useless-and-just-made-my-os-swap-a-little-more MB.

A process gone is a deadly performance issue ;-) but maybe I am not on the
good newsgroup...


[quoted text, click to view]
Philipp Schumann
2/23/2005 4:54:37 PM
I have no insight into the inner workings of Reflection, and I do agree that
if Reflection info objects are cached such behaviour SHOULD be documented,
if only to prevent others from creating their own caching hashtables to
store MemberInfos and stuff (as I did at some point because I figured the
slow thing about Reflection might just be the reflection bit - reading and
parsing the metadata - rather than the dynamic invocation).

However --

am I correct in understanding that the ~5000 objects are all of different
classes? I have to assume they are generated dynamically using Reflection
Emit or something. I'm not sure Reflection, or indeed the .NET Framework,
was ever designed with applications of such a scale in mind, regardless of
whether it is an architecturally reasonable thing to do so or not. That
said, because you can safely assume that:

- in most cases, the infos read by reflection will not change during the
lifetime of your application once an Assembly is loaded into your app domain
- most assemblies will have reasonably small numbers of types and members

I wouldn't be surprised if the cache is indeed designed not to be cleared at
all - considering the two points above, why would you want to? So, while I
have no insight into the API design of Reflection, I suggest this behaviour
might just be by design...

"Questionner" <Questionner@discussions.microsoft.com> schrieb im Newsbeitrag
news:60505443-593E-44C4-B322-17CD600C8B0E@microsoft.com...
[quoted text, click to view]

AddThis Social Bookmark Button