Sobes.tech
Middle+

Ako funguje zberač odpadkov v jazyku Go?

sobes.tech AI

Odpoveď od AI

Zberač odpadu v Go implementuje paralelnú, nepresnú (non-generational) metódu založenú na algoritme Mark-and-Sweep s triggerom podľa objemu haldy.

Hlavné princípy práce:

  1. Trigger aktivácie: Zberač sa spustí, keď objem vyhradeného pamäťového priestoru prekročí určitý prah. Tento prah sa dynamicky reguluje.
  2. Fáza označovania (Mark Phase):
    • Zberač pozastaví vykonávanie iba kritickej časti fázy označovania (Stop-the-World, STW), ale to trvá veľmi krátky čas.
    • Paralelne s bežiacim programom (mutator), zberač prechádza grafom objektov založeným na koreňových ukazovateľoch (registre, globálne premenné, zásobníky gorútin).
    • Živé (dostupné) objekty sú označené ako používané.
  3. Fáza prechádzania (Sweep Phase):
    • Po dokončení fázy označovania zberač prechádza zoznam prenajatej pamäti (spans).
    • Neoznačené objekty sa považujú za odpad a ich pamäť sa uvoľní.
    • Táto fáza sa tiež vykonáva paralelne s prácou programu.
  4. Write Barrier: Go používa write barrier na sledovanie zmien v grafe objektov počas paralelnej fázy označovania. To zabezpečuje správnu prácu zberača, aj napriek modifikáciám pamäte od mutatoru.
  5. Žiadne generácie: Na rozdiel od niektorých iných jazykov, Go nedelí objekty na generácie. Zberač spracováva celú haldu úplne.
  6. Cieľ nízkej latencie: Pri navrhovaní GC v Go bola stanovená úloha minimalizovať oneskorenia spôsobené zberom odpadu (STW prestávky), čo ho robí vhodným pre serverové aplikácie.

Paralelnosť a použitie write barrier umožňujú zberaču minimalizovať čas zastavenia programu, zabezpečujúc vysokú výkonnosť.

Príklad zjednodušeného spravovania pamäti (nie priamo GC, ale ilustruje uvoľňovanie zdrojov):

package main

import (
	"fmt"
	"os"
)

func main() {
	// Príklad vytvorenia dočasného zdroja, ktorý bude uvoľnený
	file, err := os.Create("temp.txt")
	if err != nil {
		fmt.Println("Chyba pri vytváraní súboru:", err)
		return
	}
	// Odložené zatvorenie súboru.
	// Hoci to nie je GC v čistom zmysle, demonštruje uvoľňovanie zdrojov.
	defer file.Close()

	fmt.Println("Súbor 'temp.txt' vytvorený.")

	// Následne program môže pracovať so súborom...

	// GC pracuje automaticky na pozadí na zber nepoužívaných objektov v halde.
	// Napríklad, ak vytvoríme slice alebo mapu:
	data := make([]int, 1000000) // Vyhradenie v halde
	_ = data // Použitie

	// Keď data prestane byť dostupná (napríklad pri ukončení funkcie),
	// zberač odpadu časom uvoľní vyhradenú pamäť.
}