I got this question today (through the blog) and normally I don't really answer questions sent to me directly through the blog for a couple of reasons already mentioned in the Contacting Tess... post, mostly because I don't have the time to answer all the emails that drop in, but also because I feel that the blog should benefit everyone so I am much more apt to answer questions posted in comments so everyone can benefit from the answer.
Having said this, I felt that this was a question that lent itself well for answering in a post.
I've been enjoying your blog posts and wondered if I could ask you a question. I'm not sure whether or not I may have a memory leak problem. I have been monitoring thru perfmon and found that I have high private bytes ( 600 - 700MB) while my #bytes in all heaps ( 300 -350 mb). Bytes in loader heaps is 75MB number of assemblies climbs and then remains constant at 1500 or so. They all rise with each other and stay stable once they reach a plateau but they never go down until the apppool is re-cycled at 1 am. Traffic definitely goes down before then. My % in GC seems very good at right around 10-15% or less throughout the day. I was wondering if this sounds like a leak problem to you. The fact that the memory isn't released seems a problem to me. Thanks in advance.
Win2003 ASP.Net 1.1
The answer is very much dependent on what happens when it plateaus, i.e. does it plateau when the site goes idle/very low traffic or does it plateau while site usage is high?
1500 assemblies sounds like a bit much so I would definitely look into what they are. Note that the bytes in loader heap does not include the size of the assemblies themselves, only the type definitions etc. so from just this brief description I would venture to guess that a lot of the gap between private bytes and # bytes in all heaps can probably be attributed to the high number of assemblies.
1st scenario - plateaus when it goes idle...
If this is the case you can't really say if it is a leak or not. Garbage Collection will only occurr on allocations so if noone is making any allocations then no garbage collection will occurr and thus the memory usage for the .net heaps will stay pretty flat.
If it plateaus when it goes idle it is also impossible to say if the high number of assemblies stem from an assembly leak like this one, or if it comes from having a lot of sites in the same application pool, or if it comes from having debug=true in web.config. If you don't know what the assemblies are you might want to take a memory dump of the process (adplus -hang -pn w3wp.exe) and run !dumpdomain to see what they are.
Assemblies won't be unloaded until the appdomain is unloaded.
2nd scenario - plateaus when the site is still busy
If this is the case then chances are that it isn't dynamic assemblies but a hang dump will still help you determine if it is. As for the .NET memory usage in a scenario like this i would suspect that the memory is held in cache or session or something like that (a bit more static) so that is why it isn't garbage collected.
In this case I would also take a hang dump and run through the same steps as in the .NET memory lab to figure out why the objects on the heap stick around.
Hope this helps,
I've seen a situation where the XSLT files, over time, get compiled with Reflection.Emit (if I remember correctly), and are never collected (as Ref.Emit libraries are never collected). XSLT or other compiled scripts would explain the high number of assemblies, and if the number doesn't go up while the memory usage doesn't go up, then it makes sense that this would be your issue...
Thanks for the reply! I believe I fall into the 2nd scenario. I have multiple applications running in the process so I think that is why the assembly count is high. I also have caching turned on. I don't do any XSLT stuff so that isn't it. Working on testing my windbg chops right now to get a dump and analyze that.