I am trying to track down a performance issue related to garbage collection, and one symptom is that the "Promoted Finalization-Memory from Gen0" counter shows a very large number of objects with finalizers are being created and making their way out of Gen 0 after each Gen0 collection.
How can I discover what these objects are?
You can use WinDbg, with the SOS extension to find out what objects are living in Gen 0.
Attach WinDbg to your .NET app and load SOS - here's a handy tip, found here:
http://www.wintellect.com/blogs/jrobbins/automatically-load-the-right-sos-for-the-minidump
Basically type the following command:
!analyze –v
This should download the correct SOS.DLL file for you. If that fails you can run these two commands:
.loadby sos clr
or
.loadby sos mscorwks
I forget which one should work (I think you need the first one if the .NET app is .NET 4.0 and above), but try both. Next, try the following command !dumpheap:
!dumpheap -gen 0
This should show you a listing of all the objects in Gen 0. This hopefully will help you.
EDIT:
Here's a YouTube video showing how to use WinDbg to debug .NET apps:
https://www.youtube.com/watch?v=yVzNrz1jJHU
Another way to do this is with the finalizequeue command provided by SOS. This shows all objects registered for finalization, not just those that are ready for finalization:
0:010> !finalizequeue
SyncBlocks to be cleaned up: 0
Free-Threaded Interfaces to be released: 0
MTA Interfaces to be released: 0
STA Interfaces to be released: 0
----------------------------------
generation 0 has 33 finalizable objects (000000001b2b9710->000000001b2b9818)
generation 1 has 2 finalizable objects (000000001b2b9700->000000001b2b9710)
generation 2 has 580 finalizable objects (000000001b2b84e0->000000001b2b9700)
Ready for finalization 0 objects (000000001b2b9818->000000001b2b9818)
Statistics for all finalizable objects (including all objects ready for finalization):
MT Count TotalSize Class Name
000007feebb95cb8 1 24 System.Threading.OverlappedDataCache
000007feebb81168 1 24 System.LocalDataStoreHolder
000007feebb14630 1 24 System.Threading.TimerHolder
000007feebb63a38 1 32 Microsoft.Win32.SafeHandles.SafePEFileHandle
000007feebb5ae38 1 32 Microsoft.Win32.SafeHandles.SafeFileMappingHandle
000007feebb5ada8 1 32 Microsoft.Win32.SafeHandles.SafeViewOfFileHandle
...<snip>...
Total 615 objects
Then you can dump all objects in the generation 1 range of memory (clipping off the end since it won't be inclusive). I only have two in generation 1 here, fortunately:
0:010> dd 000000001b2b9700 000000001b2b9710-4
00000000`1b2b9700 02d51da0 00000000 02d51d50 00000000
Then dump those objects out (this is just the first one):
0:010> !do 02d51da0
Name: System.WeakReference
MethodTable: 000007feebb6cbb0
EEClass: 000007feeb53f1d8
Size: 24(0x18) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Fields:
MT Field Offset Type VT Attr Value Name
000007feebb6a338 4000688 8 System.IntPtr 1 instance 2128d8 m_handle
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With