We recently encountered frequent performance degradation due to high memory utilization in our ASP.NET application. I won’t go into the details of how we actually identified the source of the leak, unless there’s a considerable public outcry for such an explanation. Suffice it to say that we were able to track it down with Windbg and a few essential blog posts (below). In this case what we learned is more noteworthy than how we learned it.
What we found to be the cause of the memory leak was more or less a classic mistake, with a twist. Deep in the bowels of a fairly complex page, nested several UserControls deep there lived a DropDownList control which was being assigned to ViewState. That’s not a particularly good idea, but ordinarily that wouldn’t cause a memory leak, although it would create considerable ViewState bloat (if the DropDownList is even serializable which I never confirmed). ViewState is serialized into gobbledygook and stuffed into a hidden field. However, in this particular page ViewState persistence was being overridden to use the SessionPageStatePersister. The twist being that the serialized ViewState gobbledygook is stuffed into Session instead of a hidden field, or so I assumed.
After cracking open the SessionPageStatePersister with Reflector and comparing it to the HiddenFieldPageStatePersister I discovered a significant difference. The SessionPageStatePersister wasn’t serializing ViewState, it was a straight variable assignment. Therefore Session wasn’t storing a large string of serialized text, similar to what you’d find in the hidden field, instead it held a reference to the objects in ViewState. Further, since in this case Session was ‘in-memory’, that meant that the DropDownList and its graph (i.e. parents and other references) were being held in memory for the duration of the Session. I think you can see where this is going.
The confluence of ViewState misuse, a misunderstanding about the behavior of SessionPageStatePersister and the use of in-Memory Session conspired to create a troublesome memory leak. Hopefully those of you using a similar combination will heed our mishap and be wiser for it.