MANAGED DEBUGGING with WINDBG. Managed Heap. Part 5

Hi all,

This post is a continuation of MANAGED DEBUGGING with WINDBG. Managed Heap. Part 4.

MANAGED HEAP. Part 5

· We can troubleshoot Loader Heap issues:

An assembly can’t be unloaded while the AppDomain where it was created is still alive. We will get a memory leak if we keep creating new assemblies continuously. The problem is that some .NET operations result on new assemblies being created behind the scenes:

§ Create a new XmlSerializer with any constructor but XmlSerializer(type) or XmlSerializer(type, defaultnamespace).

Memory usage is high when you create several XmlSerializer objects in ASP.NET

§ Make XSLT transformations where XSLT Transform contains a script.

PRB: Cannot unload assemblies that you create and load by using script in XSLT

§ Change ASPX, ASCX or ASMX pages which cause re-compilations.

This could be avoided by caching XMLSerializers and XSLT Transforms, and using maxNumRecompiles value which is set to 15 by default.

Imagine that we’ve detected a memory leak in our ASP.NET app, and PerfMon shows that during the time of the memory leak “.NET CLR Loading:Bytes in loader heap” is constantly increasing. The same thing is true for “.NET CLR Loading:Current Assemblies”. We check the number of assemblies in the heap:

0:000> !DumpHeap -stat -type Assembly

------------------------------

Heap 0

total 1141 objects

------------------------------

Heap 1

total 1220 objects

------------------------------

total 2361 objects

Statistics:

MT Count TotalSize Class Name

7912ad0c 1 24 System.Collections.Generic.List`1[[System.Reflection.Assembly, mscorlib]]

...

790fc79c 2297 55128 System.Reflection.Assembly

Total 2361 objects

And we try to get some info about those assemblies:

0:000> !DumpDomain

...

--------------------------------------

Domain 2: 001cb1d8

LowFrequencyHeap: 001cb1fc

HighFrequencyHeap: 001cb258

StubHeap: 001cb2b4

Stage: OPEN

SecurityDescriptor: 001c9ab0

Name: /LM/w3svc/1/ROOT/DebuggingWorkshop-1-128030642795871345

Assembly: 001b6660 [C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll]

ClassLoader: 001773b8

SecurityDescriptor: 642a2e7e

Module Name

790c2000 C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll

02272380 C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\sortkey.nlp

02272010 C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\sorttbls.nlp

...

Assembly: 0020b220 [C:\WINDOWS\assembly\GAC_MSIL\System.Drawing\2.0.0.0__b03f5f7f11d50a3a\System.Drawing.dll]

ClassLoader: 0020c808

SecurityDescriptor: 642a2e7e

Module Name

7ae72000 C:\WINDOWS\assembly\GAC_MSIL\System.Drawing\2.0.0.0__b03f5f7f11d50a3a\System.Drawing.dll

Assembly: 0020e778 [3k2vmufw, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]

ClassLoader: 0020e800

SecurityDescriptor: 642a2e7e

Module Name

02837b58 3k2vmufw, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

Assembly: 0021c050 [zxsplww6, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]

ClassLoader: 0021c0d8

SecurityDescriptor: 642a2e7e

Module Name

02837f34 zxsplww6, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

...

Assembly: 14bdbf88 [oy_7tsbs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]

ClassLoader: 14bdc010

SecurityDescriptor: 642a2e7e

Module Name

19a273d8 oy_7tsbs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

0:000> !DumpModule 19a273d8

Name: oy_7tsbs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

Attributes: PEFile

Assembly: 14bdbf88

LoaderHeap: 00000000

TypeDefToMethodTableMap: 19bf6158

TypeRefToMethodTableMap: 19bf6170

MethodDefToDescMap: 19bf61dc

FieldDefToDescMap: 19bf6250

MemberRefToDescMap: 19bf62b8

FileReferencesMap: 19bf63fc

AssemblyReferencesMap: 19bf6400

MetaData start address: 19c312d8 (6176 bytes)

0:000> dc 19c312d8 19c312d8+6176

19c312d8 424a5342 00010001 00000000 0000000c BSJB............

...

19c319e8 00010000 0000039b 00000000 6f4d3c00 .............<Mo

19c319f8 656c7564 796f003e 7374375f 642e7362 dule>.oy_7tsbs.d

19c31a08 58006c6c 65536c6d 6c616972 74617a69 ll.XmlSerializat

19c31a18 576e6f69 65746972 72755072 73616863 ionWriterPurchas

19c31a28 64724f65 4d007265 6f726369 74666f73 eOrder.Microsoft

19c31a38 6c6d582e 7265532e 696c6169 6974617a .Xml.Serializati

19c31a48 472e6e6f 72656e65 64657461 65737341 on.GeneratedAsse

19c31a58 796c626d 6c6d5800 69726553 7a696c61 mbly.XmlSerializ

19c31a68 6f697461 6165526e 50726564 68637275 ationReaderPurch

19c31a78 4f657361 72656472 6c6d5800 69726553 aseOrder.XmlSeri

...

We check our code and we can see this:

protected void Page_Load(object sender, EventArgs e)

{

XmlSerializer mySerializer = new XmlSerializer(typeof(PurchaseOrder), new XmlRootAttribute("order"));

...

}

We can see how much memory is taken up by the Loader heap:

0:000> !EEHeap -loader

Loader Heap:

...

--------------------------------------

Module Thunk heaps:

Module 648e8000: Size: 0x0(0)bytes.

Module 68a06000: Size: 0x0(0)bytes.

...

Module 19a273d8: Size: 0x0(0)bytes.

Total size: 0x0(0)bytes

--------------------------------------

Total LoaderHeap size: 0xe33000(14888960)bytes

=======================================

0:000> !DumpModule 19a273d8

Name: oy_7tsbs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

...

Next post: MANAGED DEBUGGING with WINDBG. Breaking on an Exception. Part 1.

Index: MANAGED DEBUGGING with WINDBG. Introduction and Index.

Regards,

Alex (Alejandro Campos Magencio)