2015-11-12 16 views
7

Podczas przechwytywania pliku zrzutu i jego analizy (np. W WinDbg), często otrzymuję ostrzeżenie, że dane mogą być niedokładne lub polecenia mogą być niedostępne, ponieważ proces był w trakcie GC, gdy zbierano plik zrzutu.Jak przechwycić zrzut pamięci procesu procesu .NET, gdy .NET nie znajduje się w środku zbierania śmieci (GC)

Wykonując analizę pamięci, często robimy to, ponieważ pamięć w procesie jest wysoka, a ciśnienie w pamięci jest wysokie, co, jak sądzę, często wymusza system .NET na GC.

Jak uniknąć wykonywania zrzutów podczas GC? Czy istnieje sposób, aby dowiedzieć się, kiedy można bezpiecznie przechwycić plik zrzutu?

+2

Możesz chcieć użyć PerfView, który został zaprojektowany z myślą o tym problemie. Pomoc | Przewodnik użytkownika zawiera sekcję o nazwie "Kolekcja GC Heap: zamrozić lub nie zamrozić?" który to omawia. Łącze pobierania: http://www.microsoft.com/en-us/download/details.aspx?id=28567 –

+0

Napisz do mnie, jeśli potrzebujesz pomocy, wprowadzając/testując moją odpowiedź. –

+0

@ Mark: Czy w twojej aplikacji są jakieś procesy działające w tle? Chodzi mi o to, że jeśli użytkownik go nie używa, może nadal przetwarzać coś za sceną? – CharithJ

Odpowiedz

4

Nie jestem ekspertem w tej dziedzinie, ale zauważyłem, że można używać liczników wydajności środowiska wykonawczego .NET do monitorowania interesujących rzeczy - jedną z nich jest liczba bajtów przydzielonych przez garbage collector podczas jego ostatniej kolekcji. Opis Allocated Bytes/second w Performance Counters in the .NET Framework stanów:

wyświetla liczbę bajtów na sekundę alokowanych na stercie zbierania śmieci. Ten licznik jest aktualizowany na końcu każdego procesu czyszczenia pamięci, a nie przy każdej alokacji. Ten licznik nie jest średnią z upływem czasu; wyświetla różnicę między wartościami obserwowanymi w dwóch ostatnich próbkach podzieloną przez czas trwania przedziału próbkowania.

Według moich badań, jeśli ustawisz interwał aktualizacji monitora wydajności na 1 sekundę i przyjrzyj na wskaźnik Allocated Bytes/second, wydaje się, aby pokazać wartość 0 po kolekcja została zakończona. Zakładam więc, że możesz czerpać z tej wartości, czy kolekcja jest w toku, czy nie.

Sprawdziłem to, budując małą aplikację w VS 2015, która może pokazać, czy trwa proces zbierania śmieci. Wartość wskaźnika była inna niż 0, gdyby tak było.

Aktualizacja (Dzięki Thomas)

Jest możliwe użycie ProcDump do monitorowania liczników wydajności i tworzenia zrzutu w sposób zautomatyzowany. Prawidłowy sposób to: procdump ProcessName -s 1 -ma -pl "\.NET CLR Memory(ProcessName)\Allocated Bytes/second" 1000, który uruchomi zrzut, jeśli wartość spadnie poniżej tysiąca.

Powinno to zadziałać, ponieważ wartość wynosi zero, tylko jeśli nie ma zbierania śmieci.

Jeśli nie pracujesz w angielskiej wersji systemu operacyjnego, musisz znaleźć właściwą nazwę językową licznika wydajności (można to zrobić, patrząc na łącze MSDN podane powyżej i przełączając się na inny tam język). Na przykład. niemiecka nazwa będzie być "\.NET CLR-Speicher(ProcessName)\Zugeordnete Bytes/Sek.".

+0

Dzięki za odpowiedź. Czy możesz udzielić odpowiedzi nieco bardziej praktycznej? Czy to oznacza, że ​​możemy użyć [ProcDump] (https://technet.microsoft.com/en-us/sysinternals/dd996900.aspx) z przełącznikiem '-pl'? Jeśli tak, to jaki? Czy możesz podać przykładowy kod, aby udowodnić teorię? –

+1

Dziękujemy za zaktualizowaną odpowiedź. Dam temu szansę. –

+0

@Thomas Dzięki za nagrodę ;-) –

Powiązane problemy