Welche Art von Garbage Collection verwendet Go?

111

Go ist eine Müllsammelsprache:

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

Hier heißt es, dass es sich um einen Mark-and-Sweep-Garbage-Collector handelt, der sich jedoch nicht mit Details befasst, und ein Ersatz ist in Arbeit ... dennoch scheint dieser Absatz seit der Veröffentlichung von Go nicht viel aktualisiert worden zu sein.

Es ist immer noch Mark-and-Sweep? Ist es konservativ oder präzise? Ist es generationsübergreifend?

user1003432
quelle
2
Eine lange Diskussion über die Geschichte des Müllsammlers Go bis Juli 2018 finden Sie unter blog.golang.org/ismmkeynote
Wildcard

Antworten:

117

Pläne für den Müllsammler Go 1.4+:

  • Hybrid-Stop-the-World / Concurrent-Kollektor
  • Stop-the-World-Teil durch eine Frist von 10 ms begrenzt
  • CPU-Kerne für die Ausführung des Concurrent Collector
  • Dreifarbiger Mark-and-Sweep-Algorithmus
  • nicht generationsübergreifend
  • nicht verdichtend
  • voll präzise
  • Es entstehen geringe Kosten, wenn das Programm Zeiger bewegt
  • geringere Latenz, aber höchstwahrscheinlich auch geringerer Durchsatz als Go 1.3 GC

Go 1.3 Garbage Collector-Updates zusätzlich zu Go 1.1:

  • gleichzeitiger Sweep (führt zu kürzeren Pausenzeiten)
  • voll präzise

Go 1.1 Müllsammler:

  • Mark-and-Sweep (parallele Implementierung)
  • nicht generationsübergreifend
  • nicht verdichtend
  • meist präzise (außer Stapelrahmen)
  • stopp die Welt
  • Bitmap-basierte Darstellung
  • Null Kosten, wenn das Programm keinen Speicher zuweist (dh: Das Mischen von Zeigern ist so schnell wie in C, obwohl dies in der Praxis etwas langsamer als C läuft, da der Go-Compiler nicht so fortgeschritten ist wie C-Compiler wie GCC).
  • unterstützt Finalizer für Objekte
  • Es gibt keine Unterstützung für schwache Referenzen

Go 1.0 Garbage Collector:

  • Wie Go 1.1, aber anstatt größtenteils präzise zu sein, ist der Garbage Collector konservativ. Der konservative GC kann Objekte wie [] Byte ignorieren.

Das Ersetzen des GC durch einen anderen ist umstritten, zum Beispiel:

  • Mit Ausnahme sehr großer Haufen ist unklar, ob ein Generations-GC insgesamt schneller wäre
  • Das Paket "unsicher" macht es schwierig, eine vollständig präzise GC zu implementieren und GC zu komprimieren

quelle
Außerdem weist der aktuelle Garbage Collector einen gewissen Grad an Parallelität auf, sodass er auf Mehrkernsystemen schneller ausgeführt werden kann.
Uriel
3
@uriel: Ja, ich habe dies im ersten Punkt meiner Antwort erwähnt - dem Text "(parallele Implementierung)".
Ist diese Antwort noch aktuell?
Kim Stebel
c # Garbage Collector ist präzise und in c # wie in go können Sie auf ein Mitglied eines geschlagenen verweisen und c # haben einen unsicheren Modus, aber ich bin nicht sicher, wie es sich mit einer unsicheren Implementierung vergleichen lässt
skyde
3
Wie wäre es, wenn Sie diese Antwort mit 1.5.x aktualisieren, um ein gutes Verlaufsprotokoll zu erstellen.
Ismael
32

(Für Go 1.8 - Q1 2017 siehe unten )

Das nächste Go 1.5 gleichzeitig Garbage Collector von beinhaltet das "Tempo", sagte gc. In diesem Artikel
wird ein Vorschlag vorgestellt , der möglicherweise für Go 1.5 geeignet ist, aber auch zum Verständnis des GC in Go beiträgt.

Sie können den Zustand sehen vor 1.5 sehen (Stop The World: STW)

Vor Go 1.5 hat Go einen parallelen Stop-the-World- Kollektor (STW) verwendet.
Während die STW-Sammlung viele Nachteile hat, weist sie zumindest ein vorhersehbares und kontrollierbares Heap-Wachstumsverhalten auf.

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

(Foto aus der GopherCon 2015- Präsentation " Go GC: Lösen des Latenzproblems in Go 1.5 ")

Der einzige Abstimmknopf für den STW-Sammler war „GOGC“, das relative Haufenwachstum zwischen den Sammlungen. Die Standardeinstellung 100% löste jedes Mal eine Speicherbereinigung aus, wenn sich die Heap-Größe gegenüber der Live-Heap-Größe gegenüber der vorherigen Sammlung verdoppelte:

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

GC-Timing im STW-Kollektor.

Go 1.5 führt einen gleichzeitigen Kollektor ein .
Dies hat viele Vorteile gegenüber der STW-Sammlung, aber es m erschwert jedoch die Kontrolle des Heap-Wachstums, da die Anwendung Speicher zuweisen kann, während der Garbage Collector ausgeführt wird .

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

(Foto von der GopherCon 2015 Präsentation "Go GC: Lösen des Latenzproblems in Go 1.5 ")

Um das gleiche Heap-Wachstumslimit zu erreichen, muss die Laufzeit die Garbage Collection früher starten. Wie viel früher, hängt jedoch von vielen Variablen ab, von denen viele nicht vorhergesagt werden können.

  • Starten Sie den Collector zu früh, und die Anwendung führt zu viele Speicherbereinigungen durch, wodurch CPU-Ressourcen verschwendet werden.
  • Starten Sie den Kollektor zu spät, und die Anwendung überschreitet das gewünschte maximale Heap-Wachstum.

Um das richtige Gleichgewicht zu erreichen, ohne die Parallelität zu beeinträchtigen, muss der Garbage Collector sorgfältig auf und ab gehen.

Die GC-Stimulation zielt darauf ab, in zwei Dimensionen zu optimieren: Heap-Wachstum und vom Garbage Collector genutzte CPU.

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

Das Design der GC-Stimulation besteht aus vier Komponenten:

  1. ein Schätzer für den Umfang der Scanarbeit, die ein GC-Zyklus erfordert,
  2. einen Mechanismus für Mutatoren, um die geschätzte Menge an Scanarbeit bis zum Erreichen des Heap-Ziels durch die Heap-Zuweisung auszuführen;
  3. ein Scheduler für das Scannen im Hintergrund, wenn der Mutator das CPU-Budget nicht ausnutzt, und
  4. ein Proportionalregler für den GC-Trigger.

Das Design gleicht zwei verschiedene Zeitansichten aus: CPU-Zeit und Heap-Zeit .

  • Die CPU-Zeit entspricht der Standard-Wanduhrzeit, vergeht jedoch GOMAXPROCSschneller.
    Das heißt, wenn GOMAXPROCSes 8 ist, vergehen acht CPU-Sekunden pro Wandsekunde und GC erhält jede Wandsekunde zwei Sekunden CPU-Zeit.
    Der CPU-Scheduler verwaltet die CPU-Zeit.
  • Der Durchlauf der Heap-Zeit wird in Bytes gemessen und bewegt sich vorwärts, wenn Mutatoren zuweisen.

Die Beziehung zwischen Heap-Zeit und Wandzeit hängt von der Zuordnungsrate ab und kann sich ständig ändern.
Mutator unterstützt die Verwaltung des Heap-Zeitverlaufs und stellt sicher, dass die geschätzte Scan-Arbeit abgeschlossen ist, wenn der Heap die Zielgröße erreicht.
Schließlich erstellt der Trigger-Controller eine Rückkopplungsschleife, die diese beiden Zeitansichten miteinander verbindet und sowohl für die Heap-Zeit- als auch für die CPU-Zeitziele optimiert.

VonC
quelle
20

Dies ist die Implementierung des GC:

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

Aus den Dokumenten in der Quelle:

Der GC wird gleichzeitig mit Mutator-Threads ausgeführt, ist typgenau (auch bekannt als präzise) und ermöglicht die parallele Ausführung mehrerer GC-Threads. Es ist eine gleichzeitige Markierung und ein gleichzeitiger Sweep, bei dem eine Schreibbarriere verwendet wird. Es ist nicht generationsübergreifend und nicht komprimierend. Die Zuordnung erfolgt unter Verwendung einer nach P-Zuordnungsbereichen getrennten Größe, um die Fragmentierung zu minimieren und im allgemeinen Fall Sperren zu beseitigen.

berdario
quelle
8

Go 1.8 GC könnte sich mit dem Vorschlag "Eliminieren des erneuten Scannens des STW-Stapels" erneut entwickeln.

Ab Go 1.7 ist das erneute Scannen des Stapels die einzige verbleibende Quelle für unbegrenzte und möglicherweise nicht triviale Stop-the-World-Zeit (STW) .

Wir schlagen vor, die Notwendigkeit eines erneuten Scannens des Stapels zu beseitigen, indem auf eine hybride Schreibbarriere umgeschaltet wird, die eine Löschschreibbarriere im Yuasa-Stil [Yuasa '90] und eine Einfügungsschreibbarriere im Dijkstra-Stil [Dijkstra '78] kombiniert .

Vorläufige Experimente zeigen, dass dies die STW-Zeit im ungünstigsten Fall auf unter 50 us reduzieren kann , und dieser Ansatz kann es praktisch machen, die Beendigung der STW-Markierung insgesamt zu eliminieren.

Die Ankündigung ist hier und Sie können sehen, dass das relevante Quell-Commit d70b0fe und früher ist.

VonC
quelle
3

Ich bin mir nicht sicher, aber ich denke, der aktuelle (Tipp-) GC ist bereits parallel oder zumindest ein WIP. Somit gilt die Stop-the-World-Eigenschaft nicht mehr oder wird es in naher Zukunft nicht mehr tun. Vielleicht kann jemand anderes dies genauer klären.

jnml
quelle
7
Es ist Stop-the-World. GC läuft möglicherweise parallel, nachdem die Welt gestoppt wurde. Sie meinten wahrscheinlich gleichzeitige GC.