Not that it matters a tremendous lot but just because it is a big pet-peeve of mine I want to differentiate between a real memory-leak and high memory usage.
A memory leak is when you used some memory and lost the pointer to the allocation so you can no longer de-allocate that memory. If you still have a pointer to it, you have high-memory usage, which might be just as bad in terms of what happens to the process but still different. Just to make things simple I’ll use the term memory leak for both of these from now on…
I like to think of solving performance and memory leak issues like peeling an onion. You take away one layer at a time, starting with the most obvious one, and then you define a limit where you determine that the problem is resolved.
There are two types of memory leaks, the gradual memory leak (where memory continuously grows at approximately the same rate) and the sudden memory jump. You troubleshoot them approximately the same way, except for in the latter case you also try to figure out if something out of the ordinary happened at the time of the jump, such as extreme load on the server etc.
So where are you leaking? As I mentioned in my previous post the process’ memory space contains a few different types of “objects” such as threads, manged object heaps, managed loader heap, native heaps, dlls, and virtual allocations, so a good place to start is by running a performance monitor log with the following counters.
- Process/Virtual Bytes
- Process/Private Bytes
- .net CLR Memory/# Bytes in all Heaps
- .net CLR Memory/% Time in GC
- .net CLR Memory/Large Object Heap size
- .net CLR Loading/Bytes in Loader Heap
- .net CLR Loading/Current Assemblies
The main thing to look for is if private bytes grow at approximately the same rate as virtual bytes and if # Bytes in all Heaps seem to follow the same curve.
If the private bytes keep increasing but # Bytes in all Heaps do not, you’re likely looking at a native memory leak (i.e. you are leaking in a COM component or similar) but if # Bytes in all heaps increase at the same rate as private bytes your leak is likely in managed code.
Much the same way, if you see a steady increase of virtual bytes but your private bytes stay pretty steady, your application probably has a problem where it is reserving a lot of virtual memory that it’s not using.
Bytes in Loader Heap and Current Assemblies should stay fairly constant once the process has started up and all app domains are loaded. If this keeps continuously increasing it is very probable that you have an assembly leak. I will write more about this later but for now, if it is an asp.net application, check that debug=false in all web.configs and that you are not running into one of the following issues.
- Memory usage is high when you create several XmlSerializer objects
- Assembly leak because of script blocks in XSLTs
So now you know approximately where you are leaking, the next step is to find out why and I will talk more about this in future posts but knowing the “where” is a big step.