Ponieważ Java 7 będzie domyślnie używać nowej funkcji czyszczenia pamięci G1, to czy Java będzie w stanie obsłużyć o rząd wielkości większą stertę bez rzekomych „niszczycielskich” czasów wstrzymania GC? Czy ktoś faktycznie wdrożył G1 do produkcji, jakie masz doświadczenia?
Szczerze mówiąc, jedyny raz, kiedy widziałem naprawdę długie przerwy w GC, dotyczyły bardzo dużych stosów, znacznie więcej niż miałaby to stacja robocza. Aby wyjaśnić moje pytanie; czy G1 otworzy bramę na sterty w setkach GB? TB?
java
garbage-collection
java-7
g1gc
benstpierre
źródło
źródło
Odpowiedzi:
Wygląda na to, że celem G1 jest krótsze czasy pauzy, nawet do punktu, w którym ma możliwość określenia maksymalnego docelowego czasu pauzy.
Zbieranie śmieci nie jest już tylko prostym rozwiązaniem typu „Hej, jest pełne, przenieśmy wszystko na raz i zacznijmy od nowa” - to fantastycznie złożony, wielopoziomowy, wątkowy system działający w tle. Może wykonywać wiele czynności konserwacyjnych w tle bez żadnych przerw, a także wykorzystuje wiedzę o oczekiwanych wzorcach systemu w czasie wykonywania, aby pomóc - na przykład zakładając, że większość obiektów umiera zaraz po utworzeniu itp.
Powiedziałbym, że czasy wstrzymania GC będą nadal się poprawiać, a nie pogarszać, w przyszłych wydaniach.
EDYTOWAĆ:
Po ponownym przeczytaniu dotarło do mnie, że codziennie używam Javy - Eclipse, Azureus i aplikacji, które tworzę, i minęło DŁUGO CZAS, odkąd zobaczyłem przerwę. Nie znacząca pauza, ale mam na myśli jakąkolwiek pauzę.
Widziałem przerwy, kiedy klikam prawym przyciskiem myszy w Eksploratorze Windows lub (czasami), kiedy podłączam określony sprzęt USB, ale z Javą - w ogóle.
Czy GC nadal jest problemem dla kogoś?
źródło
Testowałem to z ciężką aplikacją: 60-70 GB przydzielone do sterty, a 20-50 GB w użyciu w dowolnym momencie. W przypadku tego rodzaju zastosowań stwierdzenie, że przebieg może się różnić, jest niedopowiedzeniem. Używam JDK 1.6_22 w systemie Linux. Wersje podrzędne są ważne - przed około 1.6_20 w G1 były błędy, które powodowały losowe wyjątki NullPointerExceptions.
Odkryłem, że bardzo dobrze trzyma się celu pauzy, który dajesz mu przez większość czasu. Wydaje się, że domyślną przerwą jest 100 ms (0,1 sekundy), a ja mówiłem mu, aby zrobił połowę tego (-XX: MaxGCPauseMillis = 50). Jednak gdy zaczyna brakować pamięci, panikuje i całkowicie usuwa śmieci ze świata. Przy 65 GB zajmuje to od 30 sekund do 2 minut. (Liczba procesorów prawdopodobnie nie robi różnicy; prawdopodobnie jest ograniczona przez prędkość magistrali).
W porównaniu z CMS (który nie jest domyślnym GC serwera, ale powinien być dla serwerów WWW i innych aplikacji czasu rzeczywistego), typowe przerwy są znacznie bardziej przewidywalne i można je znacznie skrócić. Jak dotąd mam więcej szczęścia z CMS w przypadku dużych przerw, ale to może być przypadkowe; Widzę je tylko kilka razy w ciągu 24 godzin. Nie jestem pewien, który w tej chwili będzie bardziej odpowiedni w moim środowisku produkcyjnym, ale prawdopodobnie G1. Jeśli Oracle będzie dalej go dostrajać, podejrzewam, że ostatecznie zdecydowanym zwycięzcą będzie G1.
Jeśli nie masz problemu z istniejącymi odśmiecaczami, nie ma powodu, aby teraz rozważać G1. Jeśli używasz aplikacji o niskim opóźnieniu, takiej jak aplikacja GUI, G1 jest prawdopodobnie właściwym wyborem, z MaxGCPauseMillis ustawionym naprawdę nisko. Jeśli używasz aplikacji w trybie wsadowym, G1 nic ci nie kupi.
źródło
Chociaż nie testowałem G1 w produkcji, pomyślałem, że skomentuję, że GC są już problematyczne dla przypadków bez „ogromnych” stosów. GC może mieć poważny wpływ na usługi z, powiedzmy, 2 lub 4 koncertami. GC młodego pokolenia zwykle nie stanowią problemu, ponieważ kończą się w jednocyfrowych milisekundach (lub co najwyżej dwucyfrowych). Ale kolekcje starej generacji są znacznie bardziej problematyczne, ponieważ zajmują wiele sekund przy rozmiarach starej generacji wynoszących 1 gig lub więcej.
Otóż: teoretycznie CMS może tam bardzo pomóc, ponieważ większość operacji może działać równolegle. Jednak z biegiem czasu zdarzają się sytuacje, w których nie może tego zrobić i będzie musiał wrócić do zbiórki „stop the world”. A kiedy to się stanie (powiedzmy po 1 godzinie - niezbyt często, ale wciąż za często), no cóż, trzymaj się swoich pieprzonych czapek. Może to zająć minutę lub dłużej. Jest to szczególnie problematyczne w przypadku usług, które próbują ograniczyć maksymalne opóźnienia; zamiast, powiedzmy, 25 milisekund, aby obsłużyć żądanie, zajmuje teraz dziesięć sekund lub dłużej. Aby dodać obrażenia do obrażeń, klienci często przekraczają limit czasu i ponawiają żądanie, co prowadzi do dalszych problemów (tzw. „Burza gówna”).
Jest to jeden obszar, w którym G1 miał nadzieję bardzo pomóc. Pracowałem dla dużej firmy, która oferuje usługi w chmurze do przechowywania i wysyłania wiadomości; i nie mogliśmy użyć CMS, ponieważ chociaż przez większość czasu działał lepiej niż równoległe odmiany, miał te załamania. Tak więc przez około godzinę było fajnie; a potem coś uderzyło w wentylator ... a ponieważ usługa była oparta na klastrach, kiedy jeden węzeł miał kłopoty, inne zazwyczaj podążały za nimi (ponieważ przekroczenia czasu spowodowane przez GC prowadzą do tego, że inne węzły uważają, że węzeł uległ awarii, co prowadzi do ponownych tras).
Nie sądzę, aby GC stanowiło tak duży problem dla aplikacji, a być może nawet usługi nieklastrowe są rzadziej dotykane. Jednak coraz więcej systemów jest klastrowanych (szczególnie dzięki magazynom danych NoSQL), a rozmiary stert rosną. GC OldGen są superliniowo powiązane z rozmiarem sterty (co oznacza, że podwojenie rozmiaru sterty ponad dwukrotnie zwiększa czas GC, zakładając, że rozmiar zestawu danych na żywo również się podwoi).
źródło
CTO firmy Azul, Gil Tene, ma ładny przegląd problemów związanych z Garbage Collection i przegląd różnych rozwiązań w swojej prezentacji Understanding Java Garbage Collection and What You Can Do About It , a dodatkowe szczegóły znajdują się w tym artykule: http: // www.infoq.com/articles/azul_gc_in_detail .
C4 Garbage Collector firmy Azul w naszej JVM Zing jest zarówno równoległe, jak i współbieżne i używa tego samego mechanizmu GC zarówno dla nowej, jak i starej generacji, działając jednocześnie i kompaktując w obu przypadkach. Co najważniejsze, C4 nie ma możliwości cofnięcia się świata. Całe kompaktowanie jest wykonywane jednocześnie z uruchomioną aplikacją. Mamy klientów korzystających z bardzo dużych (setki GB) z czasem przerwy GC w gorszym przypadku <10 ms, aw zależności od aplikacji często krótszym niż 1-2 ms.
Problem z CMS i G1 polega na tym, że w pewnym momencie pamięć sterty Java musi zostać skompaktowana, a oba te moduły odśmiecania pamięci zatrzymują świat / STW (tj. Wstrzymują aplikację), aby wykonać kompaktowanie. Więc chociaż CMS i G1 mogą wypychać przerwy w STW, nie eliminują ich. Jednak C4 Azul całkowicie eliminuje przerwy w STW i dlatego Zing ma tak niskie przerwy w GC nawet dla gigantycznych rozmiarów sterty.
Aby poprawić stwierdzenie zawarte we wcześniejszej odpowiedzi, Zing nie wymaga żadnych zmian w systemie operacyjnym. Działa jak każda inna maszyna JVM na niezmodyfikowanych dystrybucjach Linuksa.
źródło
Używamy G1GC już od prawie dwóch lat. Świetnie radzi sobie w naszym systemie przetwarzania transakcji o znaczeniu krytycznym i okazał się świetnym wsparciem przy dużej przepustowości, małych przerwach, współbieżności i zoptymalizowanym zarządzaniu dużą ilością pamięci.
Używamy następujących ustawień JVM:
-server -Xms512m -Xmx3076m -XX:NewRatio=50 -XX:+HeapDumpOnOutOfMemoryError -XX:+UseG1GC -XX:+AggressiveOpts -XX:+UnlockExperimentalVMOptions -XX:MaxGCPauseMillis=400 -XX:GCPauseIntervalMillis=8000 -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime
Zaktualizowano
-d64 -server -Xss4m -Xms1024m -Xmx4096m -XX:NewRatio=50 -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:+HeapDumpOnOutOfMemoryError -XX:-DisableExplicitGC -XX:+AggressiveOpts -Xnoclassgc -XX:+UseNUMA -XX:+UseFastAccessorMethods -XX:ReservedCodeCacheSize=48m -XX:+UseStringCache -XX:+UseStringDeduplication -XX:MaxGCPauseMillis=400 -XX:GCPauseIntervalMillis=8000
źródło
Kolektor G1 zmniejsza wpływ pełnych kolekcji. Jeśli masz aplikację, w której już zmniejszyłeś zapotrzebowanie na pełne kolekcje, kolekcjoner map Concurrent Sweep jest równie dobry iz moim doświadczeniem ma krótsze mniejsze czasy odbioru.
źródło
Wygląda na to, że G1 uruchamiający JDK7u4 jest w końcu oficjalnie obsługiwany, zobacz RN dla JDK7u4 http://www.oracle.com/technetwork/java/javase/7u4-relnotes-1575007.html .
Po naszych testach dla dużych JVM dostrojony CMS nadal działa lepiej niż G1, ale myślę, że będzie się lepiej rozwijał.
źródło
Ostatnio przeniosłem się z
CMS do G1GC ze stertą 4G i 8-rdzeniowym procesorem na serwerach z JDK 1.7.45 .
(JDK 1.8.x G1GC jest preferowany od 1.7, ale z powodu pewnych ograniczeń muszę trzymać się wersji 1.7.45)
Skonfigurowałem poniżej kluczowe parametry i zachowałem wszystkie inne parametry do wartości domyślnych.
Jeśli chcesz dostroić te parametry, zapoznaj się z tym artykułem w wyroczni .
Kluczowe obserwacje:
Ale nadal cieszę się, że czas pauzy Max GC jest krótszy niż w CMS. Ustawiłem czas pauzy Max GC na 1,5 sekundy i ta wartość nie została jeszcze przekroczona.
Powiązane pytanie SE:
Wyrzucanie elementów bezużytecznych w Javie 7 (JDK 7) i dokumentacja na G1
źródło
CMS może prowadzić do powolnego obniżania wydajności, nawet jeśli jest uruchamiany bez gromadzenia nabytych obiektów. Dzieje się tak z powodu fragmentacji pamięci, której G1 rzekomo unika.
Mit o G1 dostępnym tylko z płatnym wsparciem jest po prostu mitem. Sun, a teraz Oracle wyjaśnili to na stronie JDK.
źródło
G1 GC ma działać lepiej. Ale jeśli ustawienie -XX: MaxGCPauseMill jest zbyt agresywne, śmieci będą zbierane zbyt wolno. I dlatego w przykładzie Davida Leppika uruchomiono pełne GC.
źródło
Właśnie zaimplementowałem G1 Garbage Collector w naszym projekcie Terracotta Big Memory. Podczas pracy z różnymi typami kolektorów G1 dał nam najlepsze wyniki przy czasie odpowiedzi poniżej 600ms.
Wyniki testu (łącznie 26) można znaleźć tutaj
Mam nadzieję, że to pomoże.
źródło
Niedawno przeprowadziłem migrację części Twicsy na nowy serwer ze 128 GB pamięci RAM i zdecydowałem się użyć wersji 1.7. Zacząłem od tych samych ustawień pamięci, co w 1.6 (mam kilka instancji wykonujących różne rzeczy, od 500 MB do 15 GB, a teraz nowy z 40 GB) i to wcale nie wyszło dobrze . Wydaje się, że 1.7 używa więcej sterty niż 1.6 i przez kilka pierwszych dni miałem wiele problemów. Na szczęście miałem dużo pamięci RAM do pracy i zwiększyłem pamięć RAM dla większości moich procesów, ale nadal miałem pewne problemy. Moje normalne MO polegało na użyciu bardzo małego minimalnego rozmiaru sterty 16 m, nawet przy maksymalnej sterty kilku gigabajtów, a następnie włączenie przyrostowego GC. To ograniczyło przerwy do minimum. To jednak teraz nie działa i musiałem zwiększyć minimalny rozmiar do mniej więcej tego, czego spodziewałem się średnio na stercie, i to bardzo dobrze się udało. Nadal mam włączone przyrostowe GC, ale spróbuję bez. Żadnych przerw w tej chwili i wydaje się, że wszystko przebiega bardzo szybko. Myślę więc, że morał tej historii polega na tym, że nie oczekuj, że ustawienia pamięci będą się doskonale przekładać z 1,6 na 1,7.
źródło
G1 sprawia, że aplikacja jest dużo bardziej zwinna: opóźnienie aplikacji wzrośnie - aplikację można nazwać „miękkim czasie rzeczywistym”. Odbywa się to poprzez zastąpienie dwóch rodzajów przebiegów GC (małych mniejszych i jednego dużego w Tenured Gen) na równej wielkości małe.
Aby uzyskać więcej informacji, spójrz na to: http://geekroom.de/java/java-expertise-g1-fur-java-7/
źródło
Pracuję z Javą, dla małego i dużego Heap, a pytanie o GC i Full GC pojawia się każdego dnia, ponieważ ograniczenia mogą być bardziej rygorystyczne niż inne: w pewnym środowisku 0,1 sekundy scavenger GC lub Full GC, kill po prostu fonctionnalité, a drobnoziarnista konfiguracja i możliwości są ważne (CMS, iCMS, inne ... celem jest tutaj uzyskanie najlepszego możliwego czasu odpowiedzi z leczeniem w czasie prawie rzeczywistym (tutaj leczenie w czasie rzeczywistym często wynosi 25 ms) , więc w zasadzie wszelkie ulepszenia w ergonomii i heurystyce GC są mile widziane!
źródło
Używam G1GC na Javie 8, a także z Groovy (także Java 8) i wykonuję różne rodzaje obciążeń, a ogólnie G1GC działa tak:
Zużycie pamięci jest bardzo niskie, np. 100 MB zamiast 500 MB w porównaniu z domyślnymi ustawieniami Java
Czas odpowiedzi jest stały i bardzo krótki
Wydajność między ustawieniami domyślnymi a G1GC to 20% spowolnienie podczas korzystania z G1GC w najgorszym przypadku (bez strojenia, aplikacja jednowątkowa). To niewiele, biorąc pod uwagę dobry czas odpowiedzi i niskie zużycie pamięci.
W przypadku korzystania z wielowątkowego serwera Tomcat ogólna wydajność jest o 30% lepsza, a zużycie pamięci jest znacznie niższe, a czasy odpowiedzi są znacznie niższe.
Ogólnie rzecz biorąc, podczas korzystania z naprawdę różnych obciążeń G1GC jest bardzo dobrym kolektorem Java 8 dla aplikacji wielowątkowych, a nawet w przypadku jednowątków ma pewne zalety.
źródło
Nie zaleca się używania java8 w / G1GC do obliczania punktu zmiennoprzecinkowego z JVM podobnym do hotspotu. Jest to niebezpieczne dla integralności i dokładności aplikacji.
https://bugs.openjdk.java.net/browse/JDK-8148175
JDK-8165766
JDK-8186112
źródło