2015-03-06 29 views
7

Używam systemu kompilacji. Kiedyś korzystaliśmy z kolektora CMS, ale zaczęliśmy cierpieć przy bardzo długich pełnych cyklach GC, przepustowość (czas nie robiący GC) wynosiła około 90%. Dlatego zdecydowałem się przejść na G1 z założeniem, że nawet jeśli będę miał dłuższy ogólny czas GC, przerwy będą krótsze, co zapewni wyższą dostępność. Pomysł ten wydawał się działać jeszcze lepiej niż oczekiwałem, nie widziałem pełnej GC przez prawie 3 dni, przepustowość wyniosła 97%, ogólna wydajność GC była znacznie lepsza. (Wszystkie screeny i dane dostał od GCViewer)Przerwy GC stają się naprawdę długie po kilku dniach.

Normal

Do tej pory (dzień 6). Dzisiaj system po prostu poszedł berzerk. Stara powierzchnia wykorzystywana jest zaledwie w 100%. Widzę Pełna GC wywołał niemal każde 2-3 minut lub tak, to: Berzerk!

Old wykorzystania przestrzeni: Old space

rozmiar Heap jest 20G (128g Ram łącznie). Flagi, których obecnie używam to:

-XX:+UseG1GC 
-XX:MaxPermSize=512m 
-XX:MaxGCPauseMillis=800 
-XX:GCPauseIntervalMillis=8000 
-XX:NewRatio=4 
-XX:PermSize=256m 
-XX:InitiatingHeapOccupancyPercent=35 
-XX:+ParallelRefProcEnabled 

oraz rejestrowanie flag. Czego mi się wydaje brakować to: -XX:+ParallelGCThreads=20 (Mam 32 procesory), domyślnie powinienem być 8. Przeczytałem też od Oracle, że sugeruje się, aby mieć -XX:+G1NewSizePercent=4 dla sterty 20G, domyślnie powinno być 5.

Używam 64-bitowy serwer Java HotSpot (TM) VM 1.7.0_76, Oracle Corporation

Co byś zasugerował? Czy mam oczywiste błędy? Co zmienić? Czy robię zachłanność, dając Java tylko 20G? Założeniem jest tutaj, że nadanie jej zbyt dużej ilości oznaczałoby dłuższą GC, ponieważ po prostu więcej jest do czyszczenia (chłopska logika).

PS: Aplikacja nie jest moja. Dla mnie jest to produkt pudełkowy.

+5

Wydaje mi się, że w twoim oprogramowaniu jest jakiś wyciek pamięci, który powoli zużyje dostępną przestrzeń sterty, czyniąc pracę GC coraz trudniejszą z biegiem czasu. Tak więc rozwiązania nie należy przeszukiwać w algorytmie GC ani w ustawieniach sterty (która ostatecznie zostanie wypełniona bez względu na jej rozmiar). Musisz naprawić swoje oprogramowanie lub żyć z tym, że musisz je restartować co jakiś czas. Co ciekawe, wygląda na to, że Twoja kupa nie wypełni się całkowicie, powodując awarię programu, więc może po prostu nie mam racji. –

+0

Powinieneś wkleić dziennik GC wydrukowany z '-XX: + PrintGCDetails -XX: + PrintGCTimeStamps -XX: + PrintAdaptiveSizePolicy -Xloggc: ', będzie to bardziej przydatne dla zrozumienia decyzji G1. Jeśli możesz wypróbować java 8, od tego czasu G1GC przeszedł wiele zmian. Wiele jego heurystyki zostało poprawionych, a niektóre wąskie gardła usunięte. IIRC w 7 istnieje kilka przypadków, w których G1 może sortować "malować się w rogu" – the8472

+0

Znalazłem rozwiązanie, system pozwala również użytkownikom na wykonywanie niestandardowych skryptów podczas procesu kompilacji. Po (bardzo długim) badaniu okazało się, że jeden użytkownik ciągle wykonuje skrypt, który nie zwalniał pamięci, powodując, że linia bazowa sterty stale rośnie, stąd cykl GC wydawany jest coraz rzadziej w każdej turze. –

Odpowiedz

1

Co byś zasugerował? Czy mam oczywiste błędy? Co zmienić? Czy zachowuję się chciwie, dając Java tylko 20G? Założeniem jest tutaj, że nadanie jej zbyt dużej ilości oznaczałoby dłuższą GC, ponieważ po prostu więcej jest do czyszczenia (chłopska logika).

Jeśli wyzwala pełną GCS ale swoje obłożenia pobyty w pobliżu tych 20GB to jest możliwe, że GC po prostu nie ma wystarczającej ilości miejsca do oddychania, albo aby zaspokoić popyt ogromnych odpisów lub lub spotkać się z jej celami (przepustowość , czasy pauzy), wymuszając pełne GC jako awarię.

Więc możesz spróbować zwiększyć limit sterty lub rozluźnić cele przepustowości.

Jak wspomniano wcześniej w moim komentarzu, możesz również spróbować uaktualnić do wersji java8, aby poprawić heurystykę G1.

W celu uzyskania dalszych porad przydatne byłyby logi GC dotyczące zachowania "berzerk".