MANAGED DEBUGGING with WINDBG. Managed Heap. Part 2
Hi all,
This post is a continuation of MANAGED DEBUGGING with WINDBG. Managed Heap. Part 1.
MANAGED HEAP. Part 2
· We can take a look to the objects in the heap:
We can see all objects in the heap:
0:004> !DumpHeap
Address MT Size
7b463c40 790fd0f0 12
7b463c4c 790fd8c4 36
7b463c70 790fd8c4 20
...
01905378 79119a1c 32
...
02907de0 003d6d48 16 Free
total 12400 objects
Statistics:
MT Count TotalSize Class Name
7b492254 1 12 System.Windows.Forms.VisualStyles.VisualStyleRenderer+ThemeHandle
...
79119a1c 3 96 System.Security.Policy.PermissionRequestEvidence
...
003d6d48 11 164 Free
...
790fd0f0 165 1980 System.Object
...
790fd8c4 7308 435252 System.String
Total 12400 objects
0:004> !do 01905378
Name: System.Security.Policy.PermissionRequestEvidence
...
0:004> !do 02907de0
Free Object
Size 16(0x10) bytes
Note the existence of Free objects in the heap. The Free entry represents objects which are not referenced and have been garbage collected, but whose memory hasn't been compacted and released to the operating system yet. These regions of space can be re-used by the Garbage Collector later. If 30% or more of the heap contains Free objects, the process may suffer from heap fragmentation.
I’m sure we noticed that there are too many objects in the heap, so it’s usually better to see only the statistics:
0:004> !DumpHeap -stat
total 12400 objects
Statistics:
MT Count TotalSize Class Name
7b492254 1 12 System.Windows.Forms.VisualStyles.VisualStyleRenderer+ThemeHandle
...
79119a1c 3 96 System.Security.Policy.PermissionRequestEvidence
...
003d6d48 11 164 Free
...
790fd0f0 165 1980 System.Object
...
790fd8c4 7308 435252 System.String
Total 12400 objects
We can also focus on the objects of a given type only:
0:004> !Name2EE * System.Security.Policy.PermissionRequestEvidence
Module: 790c2000 (mscorlib.dll)
Token: 0x0200048a
MethodTable: 79119a1c
...
0:004> !DumpHeap -mt 79119a1c
Address MT Size
01901ebc 79119a1c 32
01905378 79119a1c 32
019290c0 79119a1c 32
total 3 objects
Statistics:
MT Count TotalSize Class Name
79119a1c 3 96 System.Security.Policy.PermissionRequestEvidence
Total 3 objects
Or focus on objects of several types with part of the name in common:
0:004> !DumpHeap -type System.Security.Policy
Address MT Size
01901b78 7910ed68 20
...
01901ebc 79119a1c 32
...
0192971c 79119bf4 16
total 38 objects
Statistics:
MT Count TotalSize Class Name
791197b0 1 12 System.Security.PolicyManager
7911c924 1 24 System.Security.Policy.Hash
...
79119a1c 3 96 System.Security.Policy.PermissionRequestEvidence
...
790f97c4 3 156 System.Security.Policy.PolicyLevel
Total 38 objects
We can see the objects in the Large Object Heap, and we can do it in several ways:
0:004> !EEHeap -GC
Number of GC Heaps: 1
generation 0 starts at 0x01901018
generation 1 starts at 0x0190100c
generation 2 starts at 0x01901000
ephemeral segment allocation context: none
segment begin allocated size
00423878 7b463c40 7b47a744 0x00016b04(92932)
0041d178 7a733370 7a754b98 0x00021828(137256)
003d6600 790d8620 790f7d8c 0x0001f76c(128876)
01900000 01901000 01949ff4 0x00048ff4(298996)
Large object heap starts at 0x02901000
segment begin allocated size
02900000 02901000 02907df0 0x00006df0(28144)
Total Size 0xa787c(686204)
------------------------------
GC Heap Size 0xa787c(686204)
0:004> !DumpHeap 02901000 02907df0
Address MT Size
02901000 003d6d48 16 Free
02901010 7912d8f8 4096
...
total 15 objects
Statistics:
MT Count TotalSize Class Name
003d6d48 8 128 Free
7912d8f8 7 28016 System.Object[]
Total 15 objects
0:004> !SOS.DumpHeap -min 85000
...
Note that there are objects in LOH which size is smaller than 85,000 bytes (?).
We can also see the objects which are ready for finalization, and in general, which objects in our app have a Finalize method:
0:004> !FinalizeQueue
SyncBlocks to be cleaned up: 0
MTA Interfaces to be released: 0
STA Interfaces to be released: 0
----------------------------------
generation 0 has 703 finalizable objects (00457998->00458494)
generation 1 has 0 finalizable objects (00457998->00457998)
generation 2 has 0 finalizable objects (00457998->00457998)
Ready for finalization 0 objects (00458494->00458494)
Statistics:
MT Count TotalSize Class Name
7b492254 1 12 System.Windows.Forms.VisualStyles.VisualStyleRenderer+ThemeHandle
...
7ae77fa8 2 80 System.Drawing.Icon
...
7b485894 59 3776 System.Windows.Forms.Internal.DeviceContext
Total 703 objects
0:004> dd 00457998 00458494-4
00457998 01901f10 01905238 01906414 01906428
...
00457b28 019323f8 019324b0 0193296c 01936378
...
00458488 01949468 019494f0 0194959c
0:004> !DumpHeap -mt 7ae77fa8
Address MT Size
0193296c 7ae77fa8 40
01936378 7ae77fa8 40
total 2 objects
Statistics:
MT Count TotalSize Class Name
7ae77fa8 2 80 System.Drawing.Icon
Total 2 objects
0:004> !do 0193296c
Name: System.Drawing.Icon
...
0:004> !DumpMT -md 7ae77fa8
...
Name: System.Drawing.Icon
...
--------------------------------------
MethodDesc Table
Entry MethodDesc JIT Name
...
7ae2070c 7aea3c88 PreJIT System.Drawing.Icon.Finalize()
...
7ae201dc 7aea3c58 PreJIT System.Drawing.Icon.Dispose()
...
Look to the way Reflector.exe shows the Dispose and Finalize (destructor) methods of the “Icon” class we saw above, and how Dispose tells the GC to forget about the Finalize method:
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
~Icon()
{
this.Dispose(false);
}
We can get extra information on the following objects registered for finalization: SyncBlocks and RuntimeCallableWrappers (RCWs). Both of these data structures are cached and cleaned up by the Finalizer thread.
0:000> !FinalizeQueue -detail
To be cleaned Com Data
0x4edc1b8 ComPlusWrapper
0x4edc590 ComPlusWrapper
...
0x4e227b8 ComPlusWrapper
SyncBlock to be cleaned up: 6371
MTA interfaces to be released: 0
STA interfaces to be released: 0
...
Every time a COM interface pointer enters the CLR, it is wrapped in a RCW. The RCW has a reference count that is incremented every time a COM interface pointer is mapped to it. The System.Runtime.InteropServices.Marshal.ReleaseComObject method decrements the reference count. If the same COM interface is passed more than once from unmanaged to managed code, the reference count on the wrapper is incremented every time and calling ReleaseComObject returns the number of remaining references. When the reference count reaches zero, the runtime releases all its references on the unmanaged COM object. We use this method to free the COM object and the resources it holds.
Next post: MANAGED DEBUGGING with WINDBG. Managed Heap. Part 3.
Index: MANAGED DEBUGGING with WINDBG. Introduction and Index.
Regards,
Alex (Alejandro Campos Magencio)