Hunderttausende pro Go FAQ: Warum Goroutinen statt Threads? ::
Es ist praktisch, Hunderttausende von Goroutinen im selben Adressraum zu erstellen.
Der Test test / chan / goroutines.go erstellt 10.000 und könnte leicht mehr tun, ist jedoch so konzipiert, dass er schnell ausgeführt wird. Sie können die Nummer auf Ihrem System ändern, um zu experimentieren. Sie können problemlos Millionen ausführen, wenn genügend Speicher vorhanden ist, z. B. auf einem Server.
Um die maximale Anzahl von Goroutinen zu verstehen, beachten Sie, dass die Kosten pro Goroutine in erster Linie der Stapel sind. Nochmals per FAQ:
… Goroutinen können sehr billig sein: Sie haben nur wenig Overhead außerhalb des Speichers für den Stapel, der nur wenige Kilobyte beträgt.
Bei einer Back-of-the-Envelope-Berechnung wird davon ausgegangen, dass jeder Goroutine eine 4-KiB- Seite für den Stapel zugewiesen ist (4 KiB ist eine ziemlich einheitliche Größe), plus ein wenig Overhead für einen Steuerblock (wie einen Thread- Steuerblock ) für die Laufzeit; Dies stimmt mit dem überein, was Sie beobachtet haben (2011 vor Go 1.0). Somit würden 100 Ki-Routinen ungefähr 400 MiB Speicher benötigen, und 1 Mi-Routinen würden ungefähr 4 GiB Speicher benötigen, was auf dem Desktop immer noch verwaltbar ist, ein bisschen viel für ein Telefon und auf einem Server sehr verwaltbar. In der Praxis hat der Startstapel eine Größe von einer halben Seite (2 KiB) bis zwei Seiten (8 KiB), was ungefähr korrekt ist.
Die Größe des Startstapels hat sich im Laufe der Zeit geändert. es begann bei 4 KiB (eine Seite), dann wurde in 1.2 auf 8 KiB (2 Seiten) erhöht, dann wurde in 1.4 auf 2 KiB (eine halbe Seite) verringert. Diese Änderungen waren auf segmentierte Stapel zurückzuführen, die Leistungsprobleme beim schnellen Hin- und Herwechseln zwischen Segmenten verursachten ("Hot-Stack-Split"), also zur Minderung erhöht (1.2) und dann verringert, wenn segmentierte Stapel durch zusammenhängende Stapel ersetzt wurden (1.4):
Go 1.2 Versionshinweise: Stapelgröße :
In Go 1.2 wurde die Mindestgröße des Stapels beim Erstellen einer Goroutine von 4 KB auf 8 KB angehoben
Go 1.4 Versionshinweise: Änderungen an der Laufzeit :
Die Standardstartgröße für den Stapel einer Goroutine in 1.4 wurde von 8192 Byte auf 2048 Byte reduziert.
Der Speicher pro Goroutine ist größtenteils gestapelt, beginnt niedrig und wächst, sodass Sie kostengünstig viele Goroutinen haben können. Sie könnten einen kleineren Startstapel verwenden, aber dann müsste er früher wachsen (Speicherplatz auf Kosten der Zeit gewinnen), und die Vorteile nehmen ab, da der Steuerblock nicht schrumpft. Es ist möglich, den Stapel zu entfernen, zumindest wenn er ausgetauscht wird (z. B. alle Zuordnungen auf dem Heap vornehmen oder den Stapel auf dem Heap beim Kontextwechsel speichern), obwohl dies die Leistung beeinträchtigt und die Komplexität erhöht. Dies ist möglich (wie in Erlang) und bedeutet, dass Sie nur den Kontrollblock und den gespeicherten Kontext benötigen. Dies ermöglicht einen weiteren Faktor von 5 × –10 × für die Anzahl der Goroutinen, der jetzt durch die Größe des Kontrollblocks und die Größe der Goroutine auf dem Heap begrenzt ist -lokale Variablen. Dies ist jedoch nicht besonders nützlich, es sei denn, Sie benötigen Millionen winziger schlafender Goroutinen.
Da viele Goroutinen hauptsächlich für E / A-gebundene Aufgaben verwendet werden (konkret zur Verarbeitung blockierender Systemaufrufe, insbesondere von Netzwerk- oder Dateisystem-E / A), stoßen Sie viel häufiger auf Betriebssystembeschränkungen für andere Ressourcen, nämlich Netzwerksockets oder Dateihandles : Golang-Nüsse ›Die maximale Anzahl von Goroutinen und Dateideskriptoren? . Der übliche Weg, dies zu beheben, besteht darin, einen Pool der knappen Ressourcen zu erstellen oder einfach die Anzahl über ein Semaphor zu begrenzen . Siehe Beibehalten von Dateideskriptoren in Go und Begrenzen der Parallelität in Go .