G1 Garbage Collector

G1

Moduł G1 Garbage Collector jest dość nowym rozwiązaniem.  Został wprowadzony w Javie wersji 7, a ustawiony jako domyślny moduł do oczyszczania pamięci w Javie wersji 9. Celem zaimplementowania modułu G1 Garbage Collector jest zastąpienie modułu CMS Garbage Collector, który w JEP 291 został oznaczony jako przestarzały.

W tym artykule znajdziesz odpowiedzi na poniższe pytania:

  • Czym jest G1GC?
  • Czym odróżnia się od innych rozwiązań?
  • Co to jest region? Jaki ma domyślny rozmiar?
  • Jakie wprowadzono ulepszenia?
  • Jak włączyć moduł?

Charakterystyka

Algorytm zwany jest także jako algorytm niskiej latencji. Działa w trybie równoległym i współbieżnym jak CMS, ale pod spodem działa zupełnie inaczej w porównaniu do starszych modułów. Moduł G1 to regionalizowany i generacyjny moduł odśmiecania pamięci, oznacza to, że algorytm jest odpalany na regionach o jednakowych wielkości zachowując podejście oparte na generacji obiektów. Rozmiary regionów mogą się wahać od 1MB do 32MB w zależności od rozmiaru sterty. Dodatkowym warunkiem jest utworzenie nie więcej niż 2048 regionów, a więc dla sterty o rozmiarze 2GB, G1 Garbage Collector ustali 2048 regionów o rozmiarze 1MB. Struktura sterty też uległa zmianie i została podzielona na 3 główne części:

  • Eden,
  • Przestrzeń przetrwalników,
  • Stara Generacja.
Schemat sterty dla G1 Garbage Collector

Tryb pracy

Sam algorytm pracuje w czterech fazach:

  • W pierwszej fazie: zaznacza obiekty źródłowe blokując wątki aplikacyjne.
  • W drugiej fazie: zaznacza używane obiekty wychodząc od korzenia. Celem jest zaznaczenie w trybie współbieżnym jak największej ilości obiektów. Następnie obiera za cel te regiony, które zapewnią dużą ilość wolnego miejsca.
  • W trzeciej fazie: wątki aplikacyjne są zatrzymywane i dokonywana jest końcowa wersja zaznaczania.
  • W czwartej fazie: algorytm usuwa nieużywane obiekty, czyści statusy żywych obiektów, kopiuje do jednego lub więcej regionów w celu promocji i zmniejszenia fragmentacji. Ostatnia faza jest wykonywania częściowo współbieżnie.

Algorytm stara się pracować cały czas w trybie współbieżnym i unikając pracy na całej stercie, aby skrócić czas przerwy i zwiększyć przepustowość. Śledzi obszary pod kątem żywej pamięci i najpierw oczyszcza te z największą ilością śmieci.

Zwykle obiekty przydzielane są do danego regionu aż do jego zapełnienia, aby później moduł GC mógł uruchomić pracę w obrębie danego regionu i oczyścić pamięć. Jednak nie zawsze ta reguła się sprawdza. Moduł G1 Garbage Collector inaczej traktuje obiekty o dużych rozmiarach. Jeśli obiekt jest większy niż połowa rozmiaru regionu to taki obiekt jest traktowany wyjątkowo, dzięki czemu dostęp do obiektów jest zazwyczaj szybszy. Takie obiekty nazywane są jako humongous objects. Algorytm GC napotykając obiekt wykonuje następujące kroki:

  • Przydziela bezpośrednio do starej generacji.
  • Tworzony jest oddzielny region, który składa się z kilka sąsiadujących regionów.
  • Utworzony region może pomieścić tylko jeden ogromny obiekt, co oznacza, że przestrzeń w ostatnim z połączonych regionów może być prawie pusta.

Ulepszenia

Algorytm G1 Garbage Collector obowiązuje jako domyślny moduł od Javy wersji 9. Zmiana została wprowadzona w JEP 248. W kolejnych wersjach Javy wprowadzono drobne poprawki.

W JEP 307 wprowadzono do modułu tryb równoległy.  Oznacza to, że, jeśli moduł nie będzie mógł wystarczająco szybko odzyskać pamięci, będzie zmuszony do zatrzymania wątków aplikacyjnych i wyczyścić pamięć. Zmiana obowiązuje od Java 10.

W JEP 346 poprawiono moduł pod kątem częstotliwości zwracania pamięci sterty Java do systemu operacyjnego. Co za tym idzie, to możliwość zaoszczędzenia zasobów serwera. Do wersji Java 12, moduł G1 zwracał pamięć ze sterty tylko przy pełnych GC (full GC) lub podczas współbieżnego cyklu. Zatem w momencie, gdy JVM wykorzystywał tylko ułamek zasobów sterty, to G1 nie zwracał nieużywanej części do systemu operacyjnego. Od Javy 12, podczas braku aktywności moduł G1 będzie próbował wyzwalać cykl współbieżny w celu określania używanej ilości pamięci i ewentualni zwrócić do systemu.

Kolejnym usprawnieniem, który został wdrożony w Java 12 jest JEP 344. Celem jest zmieszczenie się w docelowym czasie pauzy podanego przez użytkownika. Aby osiągnąć cel, zaktualizowano heurystykę wyboru zestawów regionów, w których następnie pracuje G1. Jeśli moduł G1 odkryje, że heurystyka wyboru wielokrotnie wybiera niewłaściwy zestaw regionów tzn. moduł zbyt długo zatrzymuje wątki aplikacyjne, to przełącza na bardziej przyrostowy sposób, a dokładnie dzieli zestaw regionów na dwie części: obowiązkowe i opcjonalne. Przy czym tą drugą wykonuje jeśli starczy czasu.

W pigułce

  • Domyślny GC od Java 9.
  • Parametr: -XX:+UseG1GC.
  • Działa podobnie jak CMS Garbage Collector.
  • Podobnie jak inne moduły opiera się na generacjach, dodatkowo jako pierwszy wprowadza regiony.
  • Działa w trybie równoległym i współbieżnym.

Ciekawe artykuły:

  1. Rob, Java 10 improvements to Garbage Collection explained in 5 minutes, https://blog.idrsolutions.com/2018/04/java-10-improvements-to-garbage-collection-explained-in-5-minutes
  2. M. Beckwith, Garbage First Garbage Collector Tuning, https://www.oracle.com/technical-resources/articles/java/g1gc.html
  3. H. Choudhary, Evolution of Garbage Collection on Java: Garbage First Garbage Collection, https://medium.com/@hansrajchoudhary_88463/evolution-of-garbage-collection-on-java-garbage-first-garbage-collection-a3f39b1a9ae0
  4. Best practice for JVM Tuning with G1 GC, https://backstage.forgerock.com/knowledge/kb/article/a75965340

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *