Finding memory leak in ASP.NET website with ANTS Memory Profiler?

3k views Asked by At

I have a ASP.NET FRAMEWORK 4.0 website that has a memory leak. To find it I have installed ANTS Memory Profiler.

This is what I do :

  1. Host website in IIS7
  2. Start Ants Memory Profiler 8.1
  3. Set the we are profiling a IIS website and state the URL to this webpage (built in release)
  4. Start test and let the webpage startup (a lot of caching so about 1 min)
  5. Take Memory Snapshot when first page is loaded and stable
  6. Reload first page A LOT and see the memory raise from 110 MB (Private Bytes/Working Set -Private) to 270 MB
  7. Visit a lot of pages on the webpage and see it raise to 360 MB
  8. Push it some more and no more raise is done
  9. Take Memory Snapshot and click Class list (check Classes with source)

This will show classes that are still kept for example

sites_mypage_default_asx - 10 320 bytes and 10 live instances
usercontrols_common_pagehead_ascx - 928 bytes and 4 live instances

and so on

I belive/hope that these are the classes that will be cleaned by the GC

But this is not where the large foot print is, I have to uncheck the Classes with source to get the really large one. For example(sorted on Live size(byte)

string - 1 890 292 bytes
RuntimeMethodInfo - 990 976 bytes
RuntimePropertyInfo - 604 136 bytes
Hastable+bucket[] - 413 712 bytes

and so on.

The problem is that there is not much I can do about these, when opening Instance relation graph I will only see System. classes and there is no information about where thay are hold in my website.

When the classes with source was checked I however found a big memory leak that could be fixed(this was before the above run).

But I do not know how to take the next step? Why is my website still taking up 350 MB? 350 MB with data is a lot of data and I canĀ“t see that I cache this much data!?

What should be my next step?

1

There are 1 answers

0
Konrad Kokosa On BEST ANSWER

It not must have be a memory leak, just the memory pressure is not enough for the Garbage Collector to make more comprehensive job. To fully investigate this issue and check if it is a real memory leak you should make a long-running load test of your web page with average traffic. You can use Visual Studio Ultimate Load Testing if you are luck to have it or open source LoadUI project. During this test observe Performance Counters:

  • .NET Memory group counters, especially # Bytes in all Heaps and all Gen # heap size,
  • Process : Working Set and Process : Private bytes

After few hours of such test you will clearly see a trend of memory consumption. It might be that it will be released periodically if some threshold is exceeded. But if a memory consumption will grow all the time, you will have a more probable assumption of the memory leak. Then take a full memory dump of w3wp process at the end of memory leak and try to investigate it further.

As I am a big fan of WinDbg (it is faster, more detailed and cheaper than any GUI-based commercial tool), I suggest you to use it. Use it with Psscor2 or Psscor4 extension (depending version used by you application). After setting up the debugging environment (installing WinDbg and copying to its folder Psscor files), create a dump of the process. You can do it easily for example with help of Procdump tool:

procdump -ma <PID>

Then load dump using File -> Open Crush Dump option. Load appropriate version of Psscor:

.load psscor4

Then execute command to download symbols from Microsoft servers (if needed), make sure that you have an internet connection:

!symfix

And from now you should have access to plenty very interestings command (look for !help to list them). To see memory usage per type:

!dumpheap -stat

Which will result in a long list of types and their memory usage sorted ascending:

...
0x79b56d84    297,724    12,308,164 SomeNamespace.SomeObject
0x6983ad6c      1,177    19,751,856 SomeNamespace.SomeClass[]
0x79ba4aa0      6,544    46,300,516 System.Byte[]
0x001027a0        527    69,152,092      Free
0x79b9fb08  1,127,896    82,456,640 System.String

To see overall memory usage (iu means that also unrooted objects will be included):

!heapstat -iu

Heap             Gen0         Gen1         Gen2          LOH
Heap0         6594540      1488744     24322236     19164192
Heap1         8360908       951312     30822196     14358048
Heap2         8207144       386488     23198448     16078256
Heap3         4299844       453440     36015332     16125560
Total        39615576      5301708    179028460     93254272

Free space:                                                 Percentage
Heap0         4868516           12         3512      8692736SOH: 15% LOH: 45%
Heap1         7221256           12        66200      5232904SOH: 18% LOH: 36%
Heap2         7518052           12          520      7677824SOH: 23% LOH: 47%
Heap3         3578232           12      6606504      4098640SOH: 24% LOH: 25%
Total        28807516           72      8353592     31990912

Unrooted objects:                                           Percentage
Heap0         1688812       258828      8905748      4019992SOH: 33% LOH: 20%
Heap1         1052548       270796      9983932      5625984SOH: 28% LOH: 39%
Heap2          503560       267112      7697632      4596792SOH: 26% LOH: 28%
Heap3          571776       235440      8453980      5205176SOH: 22% LOH: 32%
Total         9691432      2179788     53539772     32143328

This information for sure will lead you to some conclusions, but further investigation is obviously possible so do not hesitate to ask.