ANTS Profiler box shot

ANTS Profiler

Finding memory leaks using ANTS Profiler

One of the more common tasks that ANTS Profiler is used for is to find memory leaks. In addition to gathering statistics about an application's performance, ANTS Profiler can also track objects created in the .NET managed runtime, making it a solid tool for finding objects that are not being freed when they are no longer being used.

A memory leak, technically, is an ever-increasing usage of memory by an application. With common desktop applications, this may go unnoticed, because a process typically frees any memory it has used on application exit. In the client/server model, however, memory leakage is a serious issue, because applications are expected to be available 24 hours a day with little or no downtime. Applications must not continue to increase their memory usage indefinitely, because that can result in a service being unavailable, or even create a stoppage for the entire computer on which the service is running!

To illustrate this, you can normally tell that an application is leaking memory if you use the Windows Performance Monitor tool, and look at its # Total committed Bytes performance counter for the .NET CLR Memory performance object. During normal usage of the application, you would see the memory usage continue to creep upwards.

Windows Performance Monitor

Microsoft's .NET runtime uses a technique known as "garbage collection" to manage memory. The garbage collector kicks in from time to time, and cleans up the memory of objects that are no longer within the "scope" of the application.

In theory, programmers should never need to worry about memory leaks. But in practice, there are technical reasons why some objects survive garbage collection even though it appears that they're no longer being used.

Now that we realize that there is a problem, we need to find the reason for it. You can use ANTS Profiler's memory profiling project to identify the number of objects that survive .NET's garbage collection, and then amend your code so that the objects are freed from memory when no longer needed.

The first step in identifying a typical memory leak is to start profiling your application by setting up a new project in ANTS Profiler, choosing the type of project, setting the appropriate arguments, and clicking GO. ANTS Profiler can analyze the object allocations for desktop applications, .NET web applications and services, Serviced Components hosted in COM+, and Windows Services. In order to profile ASP .NET web applications, membership in the local administrators' group is necessary. The first example here is a simple ASP .NET web application with the following code-behind file:

Example code

Note that this code isn't functional; it merely illustrates the creation of a few objects. The auto-generated code is omitted for brevity, but the code is otherwise correct, and runs without any errors.

After clicking GO, the web application displays in a browser window. The page is refreshed 20 times, so that the number of "live objects," that is, objects that survive garbage collection, can be counted. After this, go back to the ANTS Profiler window, and click Take Snapshot.

This generates the results. Because a lot of objects are allocated by ASP .NET, the MemLeakWebApp doesn't appear in the summary's Biggest Live Objects or Classes with the most live instances sections. Clicking the All Classes tab allows viewing of classes within the MemLeakWebApp namespace, which is the namespace for the code-behind being analyzed. This is the All Classes information:

All classes information

The only class created in the MemLeakWebApp namespace is the MyHandler1 class, of which 21 instances had survived garbage collection. Is this the desired result? Probably not. The MyHandler1 class needs to be attached to the MyStaticClass.EventHandler property. This should only be used once per page load. The question is, why are these classes surviving many page loads?

The answer to this particular question is that the MyStaticClass instance is, in case it's not entirely obvious, static. This means it will survive as long as the web application process continues to run. The net effect is that the MyStaticClass is having a new EventHandler attached at every page load. The solution is to create MyStaticClass as a public class, rather than static. A new MyStaticClass will be created at every page load, and disposed of when the page has finished loading.

Public class  MyStaticClass

In order to test the code changes, run ANTS Profiler once more by clicking GO, and refresh the web page 20 more times. This should demonstrate that a complex problem has been easily solved, hours before lunchtime!

The results now show a live count of zero, indicating that the application is not leaking memory, but still functions properly.

All classes panel

In addition to identifying memory leaks caused by objects that could not be freed because they are still referenced, ANTS Profiler's memory profiler can also show the single objects that use the most memory. The solutions to this are usually more obvious. For instance, if a web application is performing poorly, it's possible to analyze the session size. If there is a lot of data in each session, the data could be reduced by limiting the columns or rows queried from a SQL Server table, for example. In this case, there is an object in the user session that takes up 118 kilobytes of memory. Technically, this is not going to cause a memory leak, but if thousands of users access this website, the memory usage would continue climbing, causing problems on the web server.

List of objects using memory

Part of the art of finding memory leaks is that some answers come by thoroughly investigating the results. The application that produced the performance monitor results in the very first screenshot had a problem that could not easily be identified using the Biggest live objects or the Classes with the most live instances. This is the application's code:

Application code

This is the result of memory profiling the application. There was no high live count for any objects, but there are 1,000 separate classes in the Microsoft.Xslt.CompiledScripts.CSharp namespace. This application has caused the .NET Framework to dynamically generate 1,000 compiled assemblies, the same number as the number of iterations of the program's loop.

1,000 separate classes

Some research on the Internet leads here:
http://support.microsoft.com/?id=316775

This article describes a memory leak issue that happens because loading an XSL template file causes a dynamically-compiled assembly to be generated and referenced. There are two solutions: the first is to move the xslt.Load method outside the loop, so it will only run once. If this can't be avoided, the second solution is to call AppDomain.Unload, which will free the memory.

Choosing to run the xslt.Load() method only once fixes the memory leak:

Memory leak fixed

Running the performance monitor against the application again, just to make sure, results in an indication that the memory usage has stabilized.

Windows Performance Monitor

In this paper, various causes of memory leaks have been explored, providing reproducible examples of some common scenarios where memory cannot be reclaimed by the garbage collector in the .NET runtime. Various methods for analyzing different causes of memory leaks have been discussed: over-use of memory by objects that are larger than necessary, objects that cannot be freed because they are still referenced by the application, and memory leaks that occur because of technical issues deep within the inner workings of the framework.

ANTS Profiler has been demonstrated to be a vital tool in identifying and remedying these memory issues.