Middle+
Jak funguje sběrač odpadu v jazyce Go?
sobes.tech AI
Odpověď od AI
Garbage collector v jazyce Go implementuje paralelní, nepřesnou (non-generational) metodu založenou na algoritmu Mark-and-Sweep s triggerem podle objemu haldy.
Hlavní principy fungování:
- Trigger aktivace: Sběrač se spustí, když objem paměti přidělené programem překročí určitý práh, který je dynamicky regulován.
- Fáze označování (Mark Phase):
- Sběrač pozastaví pouze kritickou část fáze označování (Stop-the-World, STW), ale to trvá velmi krátkou dobu.
- Paralelně s běžícím programem (mutator) prochází graf objektů od kořenových ukazatelů (registry, globální proměnné, zásobníky gorutin).
- Přístupné (živé) objekty jsou označeny jako používané.
- Fáze úklidu (Sweep Phase):
- Po dokončení fáze označování prochází seznam paměťových spanů.
- Neoznačené objekty jsou považovány za odpad a jejich paměť je uvolněna.
- Tato fáze je také prováděna paralelně s během programu.
- Write Barrier: Go používá write barrier k sledování změn v grafu objektů během paralelní fáze označování. To zajišťuje správnou funkci sběrače i přes modifikace paměti mutátorem.
- Žádné generace: Na rozdíl od některých jiných jazyků, Go ne dělí objekty na generace. Sběrač zpracovává celou haldu jako celek.
- Cíl nízké latence: Při návrhu GC v Go bylo cílem minimalizovat zpoždění způsobená sběrem odpadků (pauzy STW), což ho činí vhodným pro serverové aplikace.
Paralelizace a použití write barrier umožňují sběrači minimalizovat dobu zastavení programu a zajistit vysoký výkon.
Příklad zjednodušené správy paměti (ne přímo GC, ale ilustruje uvolnění zdrojů):
package main
import (
"fmt"
"os"
)
func main() {
// Příklad vytvoření dočasného zdroje, který bude uvolněn
file, err := os.Create("temp.txt")
if err != nil {
fmt.Println("Chyba při vytváření souboru:", err)
return
}
// Odložené uzavření souboru.
// Ačkoliv to není GC v přímém smyslu, ukazuje uvolnění zdrojů.
defer file.Close()
fmt.Println("Soubor 'temp.txt' vytvořen.")
// Poté může program pracovat se souborem...
// GC pracuje automaticky na pozadí a sbírá nepoužívané objekty na haldě.
// Například, pokud vytvoříme slice nebo mapu:
data := make([]int, 1000000) // Alokace na haldě
_ = data // Použití
// Když data přestanou být dosažitelná (například při opuštění funkce),
// garbage collector časem uvolní přidělenou paměť.
}