Ein 40-Millisekunden-Stillstand im Go-Garbage-Collector – verursacht durch Swap
A 40ms Go garbage collector pause caused by swap

Ein Go-Prozess mit io.ReadAll und proto.Unmarshal erzeugte unter Speicherdruck 40ms lange Stop-the-World-Pausen, weil der GC seine Metadaten liest und diese durch das Kernel-Swapping auf die NVMe ausgelagert wurden. 228 Page Faults verursachten 39 der 40ms. Zusätzlich stieg der Aufbau einer 511-KiB-Nachricht von 3–5ms auf bis zu 903ms. Der Green Tea GC von Go 1.26 änderte daran nichts.
Ich habe das gemessen, und der Effekt ist vernachlässigbar.
- nasretdinov
Leider ist das einigermaßen zu erwarten – unabhängig von der Implementierung macht allein die Tatsache, dass der GC irgendwie den gesamten Baum durchlaufen muss, um noch referenzierte Bereiche zu verfolgen, Swap höchst unpraktisch – selbst wenn man keine 40-ms-Stop-the-World-Pausen hätte, würde der von Swap verwendete LRU-Cache bei jeder GC-Sammlung verworfen.
Ich glaube, das ist tatsächlich derselbe Grund, warum Apple aufgehört hat, GC in seinen Frameworks zu verwenden, und stattdessen auf automatische Referenzzählung setzt.
- jacobgold
"Es tut weh, wenn ich das mache."
"Dann lass es."
Wenn dir Latenz wichtig ist, deaktiviere Swap. Systemweit oder für das spezifische cgroup.
- pizlonator
Gibt es einen Grund, warum Go nicht On-the-fly-GC verwendet, bei der es überhaupt keine STW-Pausen gibt?
- xavdid
Discord hat das bereits 2020 gelernt und einen großartigen Blogbeitrag darüber veröffentlicht: https://discord.com/blog/why-discord-is-switching-from-go-to...
- soltanov
Ein GC-Latenz-SLO sollte den Speicherdruck des Betriebssystems einschließen. Andernfalls sieht ein Page-Fault-Problem wie ein Collector-Problem aus und führt zur falschen Lösung.
- Gabrys1
Ich habe mich gefragt, ob es einen swap-bewussten GC geben könnte, der zuerst die benötigte Seite einswap-t (nicht dass es dafür eine offensichtliche API gäbe ...) und erst dann die Welt anhält?
- imclaren
Dies. Memory-Bloat-Bugs sind in Go relativ einfach zu beheben, aber manchmal ist es ein Abenteuer, Swap-Bloat zu beseitigen. Und ich denke, es lohnt sich, allen Swap-Bloat zu beseitigen!
- faangguyindia
Ich verwende Go, wo ich Node, Ruby oder Python verwenden würde.
Ich verwende Rust, wo ich niedrige Latenz brauche.