JVM Garbage Collection Basics

Algorytmy Garbage Collectors

Garbage Collectors zazwyczaj mają następujące cele (łatwiej powiedzieć niż zrobić)

  • Bardzo krótkie „zatrzymaj świat pauzuje” z celem kilku milisekund
  • Czasy pauzy nie zwiększają się ze stertą, live-set, lub root-set size
  • Obsługuje rozmiary sterty od kilku MB do wielu TB
  • Wysoka współbieżność – Cała ciężka praca jest wykonywana, podczas gdy wątki Java kontynuują wykonywanie
  • Wysoka przepustowość
  • Wysoka wydajność
  • Łatwe do dostrojenia

Garbage Collectors

Dane w stercie są partycjonowane na wiele regionów alokacji (lub generacji), które są utrzymywane oddzielnie na podstawie wieku obiektu (tj.tj. liczby przeżytych iteracji GC). Podczas gdy niektóre kolektory są jednopokoleniowe, inne wykorzystują dwie generacje: (1) Młode Pokolenie (dalej podzielone na Eden i dwa regiony Survivor) i (2) Stare (lub Tenured) Pokolenie.
Źródło: Blog by Ionut Balosin

Dwupokoleniowe kolektory:

Seryjny GC – Algorytm wykorzystuje pojedynczy wątek do wykonania wszystkich prac związanych ze zbieraniem śmieci, co czyni go stosunkowo wydajnym, ponieważ nie ma narzutu komunikacji między wątkami. Najlepiej nadaje się do maszyn jednoprocesorowych, ponieważ nie może wykorzystać sprzętu wieloprocesorowego.

Rozdzielczy (równoległy) GC – ten algorytm używa mark-copy w Młodej Generacji i mark-sweep-compact w Starej Generacji. Obie kolekcje Young i Old wyzwalają zdarzenia stop-the-world, zatrzymując wszystkie wątki aplikacji, aby wykonać zbieranie śmieci. Oba kolektory uruchamiają fazy znakowania i kopiowania/kompaktowania przy użyciu wielu wątków, stąd nazwa 'Parallel’.

Parallel Garbage Collector jest odpowiedni dla maszyn wielordzeniowych w przypadkach, gdy głównym celem jest zwiększenie przepustowości. Większa przepustowość jest osiągana dzięki bardziej efektywnemu wykorzystaniu zasobów systemowych:

  • podczas zbierania wszystkie rdzenie równolegle czyszczą śmieci, co skutkuje krótszymi przerwami
  • pomiędzy cyklami zbierania śmieci żaden z kolektorów nie zużywa żadnych zasobów

Garbage First (G1) GC – Ten kolektor jest serwerowym zbieraczem śmieci, przeznaczonym dla maszyn wieloprocesorowych z dużą pamięcią. Z dużym prawdopodobieństwem spełnia cele czasu wstrzymania odśmiecania (GC), jednocześnie osiągając wysoką przepustowość.

  • Kolektor G1 stosuje inne podejście w zakresie modelu pamięci sterty. Sterta jest podzielona na zestaw regionów sterty o równych rozmiarach, z których każdy jest przyległym zakresem pamięci wirtualnej.
  • Pewne zestawy regionów mają przypisane te same role (eden, survivor, old), co w starszych kolektorach, ale nie ma dla nich ustalonego rozmiaru.
  • Rozmiar regionu jest wybierany przez JVM przy uruchamianiu. JVM generalnie celuje w około 2000 regionów różniących się rozmiarem od 1 do 32Mb. Kolektor G1 przyjmuje inne podejście

Więcej szczegółów można znaleźć w rozdziale Getting Started with the G1 GC

G1 Heap Allocation

Uni generational collectors:

Shenandoah GC – Shenandoah to garbage collector o niskim czasie pauzy, który zmniejsza czasy pauzy GC poprzez wykonywanie większej ilości prac związanych ze zbieraniem śmieci równolegle z uruchomionym programem Java. Shenandoah wykonuje większość pracy GC współbieżnie, w tym współbieżne zagęszczanie, co oznacza, że jego czasy pauzy nie są już wprost proporcjonalne do rozmiaru sterty. Garbage collecting a 200 GB heap or a 2 GB heap should have a similar low pause behavior.

Więcej szczegółów można znaleźć w Implementation Details w Wiki

Z GC – ZGC jest współbieżnym, jednopokoleniowym, opartym na regionach, świadomym NUMA, kompaktującym kolektorem. Fazy stop-the-world są ograniczone do skanowania roota, więc czasy wstrzymania GC nie rosną wraz z rozmiarem sterty lub żywego zbioru.

Więcej szczegółów można znaleźć w Session on ZGC by Per Liden on YouTube

Na koniec,

Epsilon GC (eksperymentalny)- GC, który obsługuje alokację pamięci, ale nie implementuje żadnego rzeczywistego mechanizmu odzyskiwania pamięci. Gdy dostępna sterta Javy zostanie wyczerpana, JVM zostanie zamknięta. Zaprojektowany do wewnętrznych testów JDK, ale może być użyteczny w dwóch sytuacjach

  • Bardzo krótko żyjące programy
  • Programy są starannie napisane, aby ponownie wykorzystać pamięć i nigdy nie wykonywać nowych alokacji

.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.