Surprisingly the issue I wrote about in "the eventhandlers that made the memory baloon" (Jan 2006) is something that still happens very frequently, I reference it in cases at least a few times a month. Just this last week I had different variations of it crop up in different cases so in this post I will show a different variation, what to look out for and how to identify it.
The issue here is a quick growth in memory, eventually causing OutOfMemory exceptions.
The problem in this case was that the application stored UI controls in session scope, i.e. Labels, DataGrids etc. in order to keep relevant information about the user throughout the session. The data they want to store is not that big, a subset of a dataset, some user related strings etc. and since it was already nicely contained in the controls there was no reason to extract them into a separate object to store in session scope.
If we look at a dropdownlist for example in memory, this is what a dropdownlist contains (the Name column contains the member variable names, and the Type column shows the type of the member variable)
So if I have a dropdownlist that contain all the US states and their abbreviations, and I want to store this in cache to avoid having to rebuild the list, a logical step to take might be to cache the dropdownlist.
However, if I do so, anything that it references will be referenced as long as the dropdownlist is in cache, so it can't be garbage collected. In the case of web controls, they all have a _parent member variable which links back to the parent control, and a _page that links back to the page where the control was originally instantiated. In other words, this means that as long as your control is in cache, you will also be caching the page, any other controls that it uses, any data bindings to data grids etc. etc.
As you can see above you will also be caching the statebag (viewstate), the IDataSource and anything it references, etc. etc. all in all it builds up to quite a bit more data than we originally bargained for, when in reality, what I wanted to store was just the list of states and abbreviations and maybe the selected item (if storing it in session scope).
Whenever you store anything in cache or session scope, make sure that you store just what you need and nothing more. If you store an object that is not a simple type like a string or an int, make sure that you know all about that object and it's member variables so that you know exactly what it is that you will be holding on to. UI objects are never good to store in cache or session scope since they contain quite a bit of extra data about their appearance and location, instead just extracting the ItemsColection and the selected item would be appropriate in the case above.
How you can identify the problem in a memory dump:
You can get a memory dump when memory is high either with Debug Diagnostics 1.1, or by running adplus -hang -pn w3wp.exe (from the debugging tools for windows).
If you open it up in windbg, and load sos (.loadby sos mscorwks) these issues are fairly easy to identify.
Running !dumpheap -stat you will see a lot of System.Web.UI items at the bottom of the output in this case.
And if you run !dumpheap -type aspx or !dumpheap -type ascx to list all the aspx/ascx pages on the heap you will likely find many of them
The next step is to take any of these pages, preferably the ones that are most plentiful like ASP.default_aspx in this case, and !gcroot some of them to figure out why they are still around
If we follow the root chain from the bottom up we see that ASP.default_aspx is a member variable of the DropDownList (the _page member variable) and that this in turn is a member variable of a NameObjectEntry in a hash table in session state. The NameObjectEntry is a key-value pair with the key and the value of a session variable, so through this we can gather that we are storing the DropDownlist in session scope.
If we look at the NameObjectEntry we can also see exactly which session variable it is (LstStates in this case)
In summary, be careful with what you store away,
No you shouldn't, this would only happen if you store it in some type of long term storage like cache/session scope/static arrays etc.
I was helping a colleague out with an OOM (OutOfMemory) situation he was dealing with. Problem description:
In some cases you may end up with the following exception when working with RadControls for ASP.NET Ajax
In your article you talk about how its not good to store too much in the cache. In my case I am only storing long strings in my cache. I even built a page that allows me to view my cached objects and keep track on how much data my cache is consuming. How much would be too much for the cache if my VPS has 1GB or ram? Also is the cache stored in the W3WP.exe? or is it stored in the aspnet_state.exe process when using a web garden? Great articles by the way
Only you can decide how much is too much... and to figure out how much is too much you will have to consider how much RAM you have vs. how many processes you are running on this system and how much memory they are consuming. You should also consider doing stress tests if you are caching very much, to see if the gain you are getting from caching superscedes that of building the cache. For example if the cache is built at the beginning of the process this might mean long startup times for the process.
Another thing to consider is that as the cache grows larger it takes longer to look through the cache to get your data. The point at which this causes an issue for you depends a lot on what you store in cache, how much you store and how long it takes to get those items if not cached.
In this particular case study the issue is not so much storing known items in cache, but rather storing UI objects and not expecting to also cache the items the UI objects reference.
A few weeks back me and Micke (one of our Architect Evangelists) had a session at TechDays where we talked
I have put together a quick and dirty debug diag script for troubleshooting .net memory leaks. (attached
I just don't understand your problem.
"the application stored UI controls in session scope, "
I hope you were not adding the complete instance of the control to the viewstate?
Well not mine:) but a lot of my customers... they weren't adding them to viewstate, but to session state.
Ok, I really wondered about ... :-)
May be the force with you
nice one but in my case i am not using the any cache or session to store UI control.
but I am enabling viewsate will increase my memory usage.
how to avoid this?
Viewstate will use some memory but whether it is an issue or not just depends on how much viewstate there is. Check view/source to see how much you have for a particular page and if you have a lot i would consider disabling viewstate at least for the controls that you dont use it for (on a per-control bases)
Hi, I tested some things realted to this.
I just created One new application and disable all the caching, session and viewstate state. and I have one Default.aspx page and i have one drpdownlist and onPageload event Just I am dynamically loading the 100000 listitem what happning you know the memoy usage of server it getting very high around 60MB and I request from the Other browser in same Pc. the Memory usage get increase to 87MB. if I increase the loop then memeury usage also getting increase. and also when I request from other pc or other browser from same Pc the memory usage getting increase.
I think even not store UI objects in cache or session scope. if we create any dynamic controls from the UI class then memory usage will get increase and It will get the above error.
Am I Correct?
Awaiting for good solution in this. because you know... my site having this Issue. My site having only 7pages and all pages having drpdownlist and I am loading the drpdownlist from the database. The memory usage of my site is always high and high never getting decrease.
Thanks And Regards