Jakiego rodzaju usługi Garbage Collection używa Go?

111

Go to język zbierania śmieci:

http://golang.org/doc/go_faq.html#garbage_collection

Tutaj jest napisane, że jest to garbage collector typu mark-and-sweep, ale nie zagłębia się w szczegóły, a zamiana jest w toku ... jednak ten akapit wydaje się nie być zbytnio aktualizowany od czasu wydania Go.

Nadal jest to znak i zamiatanie? Czy jest konserwatywne czy precyzyjne? Czy jest pokoleniowa?

user1003432
źródło
2
Długie omówienie historii śmieciarki Go do lipca 2018 r. Można
Wildcard

Odpowiedzi:

117

Plany na śmieciarkę Go 1.4+:

  • hybrydowy kolektor Stop-the-World / Concurrent
  • część typu stop-the-world ograniczona terminem 10 ms
  • Rdzenie procesora dedykowane do obsługi kolektora równoległego
  • trójkolorowy algorytm zaznaczania i przesuwania
  • niepokoleniowy
  • nie zagęszczany
  • w pełni precyzyjne
  • wiąże się z niewielkimi kosztami, jeśli program przesuwa wskaźniki
  • mniejsze opóźnienie, ale najprawdopodobniej także niższa przepustowość niż Go 1.3 GC

Idź aktualizacje garbage collectora 1.3 na dodatek Go 1.1:

  • równoczesne przeciąganie (skutkuje krótszymi przerwami)
  • w pełni precyzyjne

Śmieciarka Go 1.1:

  • mark-and-sweep (implementacja równoległa)
  • niepokoleniowy
  • nie zagęszczany
  • przeważnie precyzyjne (z wyjątkiem ramek stosu)
  • stop-the-world
  • reprezentacja oparta na bitmapie
  • zerowy koszt, gdy program nie alokuje pamięci (to znaczy: tasowanie wskaźników jest tak szybkie jak w C, chociaż w praktyce działa to nieco wolniej niż C, ponieważ kompilator Go nie jest tak zaawansowany jak kompilatory C, takie jak GCC)
  • obsługuje finalizatory na obiektach
  • nie ma wsparcia dla słabych odniesień

Go 1.0 garbage collector:

  • to samo co Go 1.1, ale zamiast być w większości precyzyjnym, odśmiecacz jest konserwatywny. Konserwatywny GC może ignorować obiekty, takie jak [] bajt.

Zastąpienie GC innym jest kontrowersyjne, na przykład:

  • z wyjątkiem bardzo dużych hałd, nie jest jasne, czy generacja GC byłaby ogólnie szybsza
  • Pakiet „niebezpieczny” utrudnia wdrożenie w pełni precyzyjnego GC i kompaktowania GC

źródło
Również obecny moduł odśmiecania pamięci ma pewien stopień równoległości, dzięki czemu może działać szybciej w systemach wielordzeniowych.
uriel
3
@uriel: Tak, wspomniałem o tym w pierwszym punkcie mojej odpowiedzi - w tekście „(implementacja równoległa)”.
Czy ta odpowiedź jest nadal aktualna?
Kim Stebel
C # garbage collector jest precyzyjny iw c # podobnie jak w go możesz mieć odniesienie do członka uderzonego i c # mieć tryb niebezpieczny, ale nie jestem pewien, jak to porównać do niebezpiecznej implementacji
skyde
3
Co powiesz na zaktualizowanie tej odpowiedzi do wersji 1.5.x tylko po to, aby zrobić dobry dziennik historii.
Ismael
32

(Dla Go 1.8 - Q1 2017, patrz poniżej )

Następny współbieżny Garbage Collector Go 1.5 obejmuje możliwość „tempa” wspomnianego gc.
Oto propozycja przedstawiona w tym artykule, która może sprawić, że będzie działać w Go 1.5, ale także pomoże zrozumieć gc w Go.

Możesz zobaczyć stan sprzed 1.5 (Stop The World: STW)

Przed Go 1.5, Go używał równoległego kolektora Stop-the-World (STW).
Chociaż zbieranie STW ma wiele wad, ma przynajmniej przewidywalne i kontrolowane zachowanie wzrostu sterty.

https://40.media.tumblr.com/49e6556b94d75de1050c62539680fcf9/tumblr_inline_nr6qq8D9FE1sdck2n_540.jpg

(Zdjęcie z prezentacji GopherCon 2015Go GC: Solving the Latency Problem in Go 1.5 ”)

Jedynym pokrętłem strojenia dla kolekcjonera STW było „GOGC”, względny wzrost sterty między kolekcjami. Domyślne ustawienie, 100%, wyzwalało wyrzucanie elementów bezużytecznych za każdym razem, gdy rozmiar sterty podwoił się w stosunku do aktualnego rozmiaru sterty od poprzedniej kolekcji:

https://docs.google.com/drawings/image?id=sLJ_JvGfPfPnojLlEGLCWkw&rev=1&h=113&w=424&ac=1

GC taktowanie w kolektorze STW.

Wersja 1.5 wprowadza współbieżny kolektor .
Ma to wiele zalet w porównaniu z kolekcjonowaniem STW, ale utrudnia kontrolowanie wzrostu sterty, ponieważ aplikacja może przydzielać pamięć podczas działania modułu odśmiecania pamięci .

https://40.media.tumblr.com/783c6e557b427a5c023520578740eb94/tumblr_inline_nr6qqpmaJx1sdck2n_540.jpg

(Zdjęcie z prezentacji GopherCon 2015Go GC: Solving the Latency Problem in Go 1.5 ”)

Aby osiągnąć ten sam limit wzrostu sterty, środowisko wykonawcze musi rozpocząć czyszczenie pamięci wcześniej, ale to, ile wcześniej jest zależne od wielu zmiennych, z których wielu nie można przewidzieć.

  • Uruchom moduł zbierający zbyt wcześnie, a aplikacja wykona zbyt wiele operacji czyszczenia pamięci, marnując zasoby procesora.
  • Uruchom kolektor zbyt późno, a aplikacja przekroczy żądany maksymalny wzrost sterty.

Osiągnięcie właściwej równowagi bez poświęcania współbieżności wymaga ostrożnego przechodzenia przez moduł odśmiecania pamięci.

Tempo GC ma na celu optymalizację w dwóch wymiarach: wzrost sterty i procesor używany przez moduł odśmiecania pamięci.

https://docs.google.com/drawings/image?id=sEZYCf7Mc0E0EGmy4gho3_w&rev=1&h=235&w=457&ac=1

Projekt stymulacji GC składa się z czterech elementów:

  1. estymator ilości pracy skanowania wymaganej przez cykl GC,
  2. mechanizm umożliwiający mutatorom wykonanie szacowanej ilości pracy skanowania do czasu, gdy alokacja sterty osiągnie cel sterty,
  3. harmonogram skanowania w tle, gdy mutator pomaga w niepełnym wykorzystaniu budżetu procesora, oraz
  4. proporcjonalny kontroler wyzwalacza GC.

Projekt równoważy dwa różne widoki czasu: czas procesora i czas sterty .

  • Czas procesora jest podobny do standardowego czasu zegara ściennego, ale płynie GOMAXPROCSszybciej.
    Oznacza to, że jeśli GOMAXPROCSwynosi 8, to osiem sekund procesora przechodzi na każdą sekundę ściany, a GC otrzymuje dwie sekundy czasu procesora na sekundę ściany.
    Program planujący procesora zarządza czasem procesora.
  • Upływ czasu sterty jest mierzony w bajtach i przesuwa się do przodu w miarę alokacji mutatorów.

Zależność między czasem sterty a czasem ściany zależy od wskaźnika alokacji i może się stale zmieniać.
Mutator pomaga zarządzać upływem czasu sterty, zapewniając, że szacowana praca skanowania została ukończona do czasu, gdy sterta osiągnie docelowy rozmiar.
Wreszcie, kontroler wyzwalacza tworzy pętlę sprzężenia zwrotnego, która łączy te dwa widoki czasu razem, optymalizując zarówno pod kątem czasu sterty, jak i czasu procesora.

VonC
źródło
20

Oto implementacja GC:

https://github.com/golang/go/blob/master/src/runtime/mgc.go

Z dokumentów w źródle:

GC działa równolegle z wątkami mutatora, jest dokładny (czyli precyzyjny), umożliwia równoległe działanie wielu wątków GC. Jest to jednoczesny znak i przeciągnięcie, które wykorzystuje barierę zapisu. Jest bezpokoleniowy i nie zagęszczający. Alokacja odbywa się przy użyciu rozmiaru posegregowanego na P obszary alokacji, aby zminimalizować fragmentację, jednocześnie eliminując blokady w typowym przypadku.

berdario
źródło
8

Go 1.8 GC może ewoluować ponownie, z propozycją „Eliminacja ponownego skanowania stosu STW”

Począwszy od wersji 1.7, jedynym pozostałym źródłem nieograniczonego i potencjalnie nietrywialnego czasu Stop-the-World (STW) jest ponowne skanowanie stosu.

Proponujemy wyeliminowanie konieczności ponownego skanowania stosu poprzez przełączenie na hybrydową barierę zapisu, która łączy barierę zapisu typu deletion write (Yuasa '90) i barierę zapisu typu insertion write (Dijkstra '78) w stylu Dijkstry .

Wstępne eksperymenty pokazują, że może to skrócić czas STW w najgorszym przypadku do poniżej 50 µs , a to podejście może sprawić, że praktyczne będzie całkowite wyeliminowanie zakończenia znaku STW.

Zapowiedź jest tu i widać istotne źródło popełnić jest d70b0fe i wcześniej.

VonC
źródło
3

Nie jestem pewien, ale myślę, że obecny (wskazówka) GC jest już równoległy lub przynajmniej jest to WIP. W ten sposób właściwość „stop-the-world” nie ma już zastosowania lub nie będzie obowiązywać w najbliższej przyszłości. Być może ktoś inny może to wyjaśnić bardziej szczegółowo.

jnml
źródło
7
To stop-the-world. GC potencjalnie działa równolegle po zatrzymaniu świata. Prawdopodobnie miałeś na myśli równoczesny GC.