Memory leaks, haven't we all been haunted by them. Your team has just completed another mayor release of your web based product. Important new features have been added and customers really like your new product. Customers rapidly start to adopt your product, deploy it on their servers and suddenly the call volume in your call center spikes. Customers report severe memory leaks under heavy usage and need to restart your application frequently to keep it up and running.
Your support and engineering team gets flooded with support incidents and your customer facing team starts screaming to get this fixed ASAP. Some of you folks might have lived through such a scenario and know how much pressure this can cause. We all know that it is not easy to find the root cause for memory leaks. Your team will spend 99% of their time identifying the root cause and 1% to fix it. There are many possible root causes for memory leaks. Memory leaking implies already what happens, memory is allocated but never freed so it can never be reused. This can be caused by a memory block being allocated and forgotten to be freed, because you instantiated an object but forgot to free it up, because of circular references, etc.
Microsoft addressed this problem in .NET, the new world of managed code. The .NET framework takes over the memory management for you. It knows any memory block allocated in your application, tracks its usage, knows when it is no longer used and then frees the memory up. This is done by the Garbage Collector and the first part of the article will explain how the GC works. But a look under the hood also shows that you still have to worry about memory allocations. You need to understand the memory allocation profile of your application so you know how effective your memory usage is and ultimately how much pressure your application puts on the GC. If your application has a mixture of many short and long lived objects then this will cause many garbage collections which ultimately can affect performance negatively. The second part of this article covers how you can use the CLR Profiler to understand the memory allocation profile of your application and how you can improve it.
A look at value types vs. reference types and stack vs. heap
The .NET framework distinguishes between value types and reference types. Value types are primitive types like Integer, Boolean, Byte, Character, etc. A variable of a value type always contains the value of that type. Passing it along as method parameter or assigning it to another variable always creates a copy of the value type. Value types are always stored on the stack. When declaring a value type .NET always assures it assigns a default value, which is always zero.
Reference types are class types, interface types, delegate types and array types. Reference types are allocated on the heap and have a pointer on the stack which points to the type on the heap. A variable of a reference type contains the pointer to the heap. Passing it along as a method parameter or assigning it to another variable copies the pointer but each pointer points to the same location on the heap.