2009-07-15 9 views
9

Monitorując naszą aplikację w Perf Mon zauważyłem, że% czasu w GC wynosi od 20 do 60%, podczas gdy nasza aplikacja wykonuje długi proces (różni się od 30 sekund do 1,5 minuty). Wydaje mi się to nieco przesadzone. Stawia to dwa ważne pytania.Powody, dla których widzimy wysoki "% czasu w GC" w Perf Mon

  1. Czy mam rację, że jest to nadmierne?
  2. Trasy, które mogę wykonać, aby dowiedzieć się, dlaczego dzieje się tak dużo GC?
+0

Czy to jest ASP.NET? –

+0

Należy zwrócić uwagę, że ten licznik wydajności pokazuje ostatnią obserwowaną wartość, a nie średnią ciągłą. Jest aktualizowany tylko pod koniec każdego cyklu GC. – adrianbanks

+0

Jest to samohostowana usługa WCF. –

Odpowiedz

12

Tak, brzmi to przesadnie. Zmniejszenie kwoty GC byłoby prawdopodobnie najlepszym krokiem do zredukowania środowiska wykonawczego aplikacji (jeśli jest to twój cel).

Wysoki "% czasu w GC" jest zwykle spowodowany przez przydzielanie, a następnie wyrzucanie tysięcy lub milionów obiektów. Dobrym sposobem, aby dowiedzieć się, co się dzieje, jest użycie narzędzia do profilowania pamięci.

Firma Microsoft zapewnia bezpłatne CLR Profiler. Spowoduje to wyświetlenie każdej alokacji, ale spowoduje, że aplikacja będzie działać 10-60 razy wolniej. Być może trzeba będzie uruchomić go na mniej danych wejściowych, aby mógł on zakończyć analizę w rozsądnym czasie.

Doskonałym narzędziem komercyjnym jest .NET Memory Profiler SciTecha. Nakłada to znacznie mniej na środowisko wykonawcze i dostępny jest bezpłatny okres próbny. Wykonując wiele migawek podczas procesu, można dowiedzieć się, jaki typ obiektów jest często przydzielany (a następnie niszczony).

Po zidentyfikowaniu źródła przydziałów należy sprawdzić kod i dowiedzieć się, w jaki sposób można zmniejszyć te przydziały. Choć nie ma jednego uniwersalnego wszystkie odpowiedzi, niektóre rzeczy, jakie napotykają w przeszłości należą:

  • String.split mogą tworzyć setki małych strun krótkotrwały. Jeśli robisz wiele manipulacji ciągami, możesz pomóc przetworzyć ciąg, przesuwając go po znaku.
  • Tworzenie tablic lub list tysięcy małych klas (na przykład poniżej 24 bajtów) może być kosztowne; jeśli te klasy mogą być traktowane jako typy wartości, może (czasami) znacznie poprawić rzeczy, aby zmienić je na struktury.
  • Tworzenie tysięcy małych tablic może znacznie zwiększyć wykorzystanie pamięci (ponieważ każda tablica ma niewielki narzut); czasami można je zastąpić jedną dużą tablicą i indeksować w podsekcję.
  • Posiadanie wielu przedmiotów możliwych do sfinalizowania (szczególnie jeśli nie są one usuwane) może wywierać duży nacisk na pojemnik na śmieci; upewnij się, że prawidłowo wyrzucasz wszystkie obiekty IDisposable i zauważ, że twoje własne typy powinny (prawie) być w stanie (prawie) never have finalizers.
  • Firma Microsoft opublikowała artykuł pod numerem Garbage Collection Guidelines w celu zwiększenia wydajności.
1

Innym powodem może być wiele kolekcji gen-1 lub gen-2, z których każda zajmuje DUŻO więcej czasu i jest spowodowana zawieszaniem się obiektów na dłuższy czas.

Widziałem to w aplikacjach internetowych, gdy błędne obiekty wisiały na rzeczywistych obiektach strony - zmuszając stronę do życia tak długo, jak inne obiekty odnoszące się do nich.

Przerwanie połączenia między obiektami i stronami (w tym przypadku) spowodowało spadek wartości GC do bardzo niskich wartości. Nasza strona ma teraz ponad 100 trafień na sekundę, a czas GC wynosi zwykle 1% lub mniej.

2

Czy mam rację, że to nadmierne?

Tak, masz rację

Trasy mogę podjąć, aby dowiedzieć się, dlaczego tak się dzieje GC?

1.- Do przyjrzeć PerfView

PerfView to narzędzie analizy wydajności, które pomaga izolować problemy z wydajnością związane z pamięcią i czynności znacznie obciążające procesor.

Zobacz także: Improving Managed Code Performance

2.- Sprawdź, czy GC.Collect lub GC.WaitForPendingFinalizers jest nazywany nigdzie w kodzie lub biblioteki osób trzecich. Te ostatnie mogą powodować wysokie wykorzystanie procesora.

Powiązane problemy