Middle+
Kaip veikia šiukšlių surinkėjas Go kalboje?
sobes.tech AI
Atsakymas iš AI
Go šiukšlių rinkėjas įgyvendina paralelinį, netikslų (non-generational) metodą, pagrįstą Mark-and-Sweep algoritmu ir veikia pagal atminties kiekio trigerį.
Pagrindiniai darbo principai:
- Trigger aktyvavimui: Šiukšlių rinkėjas pradeda veikti, kai paskirtos atminties kiekis viršija tam tikrą slenkstį. Šis slenkstis dinamiškai reguliuojamas.
- Žymėjimo fazė (Mark Phase):
- Šiukšlių rinkėjas sustabdo tik žymėjimo fazės kritinę dalį (Stop-the-World, STW), tačiau tai trunka labai trumpai.
- Paralele su veikiančia programa (mutator), jis eina per objektų grafą, pagrįstą šaknų rodyklėmis (registrai, globalios kintamosios, gorutinų stakai).
- Gyvi (pasiekiami) objektai žymimi kaip naudojami.
- Valymo fazė (Sweep Phase):
- Po žymėjimo fazės pabaigos, jis pereina per nuomojamos atminties sąrašą (spans).
- Nenurodyti objektai laikomi šiukšle ir jų atmintis laisvinama.
- Ši fazė taip pat vykdoma paraleliai su programa.
- Write Barrier: Go naudoja write barrier, kad stebėtų pokyčius objektų grafike per paralelinę žymėjimo fazę. Tai užtikrina teisingą rinkėjo darbą, nepaisant mutatoriaus atminties modifikacijų.
- Be kartų: Skirtingai nuo kai kurių kitų kalbų, Go neskaido objektų į kartas. Rinkėjas apdoroja visą krūvą pilnai.
- Žemas delsimo tikslas: Projektuojant Go GC, buvo nustatyta minimizuoti vėlavimus, kuriuos sukelia šiukšlių rinkimas (STW pauzės), todėl jis yra tinkamas serverinėms programoms.
Paralelizmas ir write barrier naudojimas leidžia rinkėjui sumažinti programos sustojimo laiką ir užtikrinti aukštą našumą.
Pavyzdys supaprastinto atminties valdymo (ne tiesioginis GC, bet iliustruoja išteklių atlaisvinimą):
package main
import (
"fmt"
"os"
)
func main() {
// Pavyzdys, kaip sukurti laikiną išteklių, kuris vėliau bus atlaisvintas
file, err := os.Create("temp.txt")
if err != nil {
fmt.Println("Klaida kuriant failą:", err)
return
}
// Failo uždarymas atidėtas.
// Nors tai nėra tiesioginis GC, tai demonstruoja išteklių atlaisvinimą.
defer file.Close()
fmt.Println("Failas 'temp.txt' sukurtas.")
// Toliau programa gali dirbti su failu...
// GC veikia automatiškai foniniame režime, surinkdama nenaudojamus objektus:
// Pavyzdžiui, jei sukuriame sąrašą ar žemėlapį:
data := make([]int, 1000000) // Paskirstymas krūvoje
_ = data // Naudojimas
// Kai data nebegalima pasiekti (pavyzdžiui, išeinant iš funkcijos),
// rinkėjas laipsniškai atlaisvins paskirstytą atmintį.
}