Как я могу узнать, какие финализуемые объекты находятся в куче 0 поколения?

Я пытаюсь отследить проблему производительности, связанную со сборкой мусора, и один из симптомов состоит в том, что счетчик "Promoted Finalization-Memory from Gen0" показывает, что очень большое количество объектов с финализаторами создаются и выходят из Gen 0 после каждая коллекция Gen0.

Как я могу узнать, что это за объекты?

3 ответа

Решение

Еще один способ сделать это с finalizequeue Команда предоставлена ​​SOS. Здесь показаны все объекты, зарегистрированные для финализации, а не только те, которые готовы к финализации:

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

Затем вы можете сбросить все объекты в диапазоне памяти 1-го поколения (отсечь конец, так как он не будет включительно). К счастью, у меня здесь только два поколения 1:

0:010> dd 000000001b2b9700 000000001b2b9710-4
00000000`1b2b9700  02d51da0 00000000 02d51d50 00000000

Затем выгрузите эти объекты (это только первый):

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

Вы можете использовать WinDbg, с SOS расширение, чтобы узнать, какие объекты живут в Gen 0,

Присоедините WinDbg к вашему приложению.NET и загрузите SOS - вот полезный совет, который можно найти здесь:

http://www.wintellect.com/blogs/jrobbins/automatically-load-the-right-sos-for-the-minidump

В основном введите следующую команду:

!analyze –v

Это должно загрузить правильный файл SOS.DLL для вас. Если это не удается, вы можете запустить эти две команды:

.loadby sos clr

или же

.loadby sos mscorwks

Я забыл, какой из них должен работать (я думаю, что вам нужен первый, если приложение.NET -.NET 4.0 и выше), но попробуйте оба варианта. Далее попробуйте следующую команду !dumpheap:

!dumpheap -gen 0

Это должно показать вам список всех объектов в Gen 0, Надеюсь, это поможет вам.

РЕДАКТИРОВАТЬ:

Вот видео на YouTube, показывающее, как использовать WinDbg для отладки приложений.NET:

https://www.youtube.com/watch?v=yVzNrz1jJHU

Вы можете использовать команду SOSEX! Finq для вывода списка всех финализируемых объектов в каждом поколении. См. Документацию SOSEX для использования.

Другие вопросы по тегам