Sobes.tech
Middle+

How does the garbage collector work in Go?

sobes.tech AI

Answer from AI

The garbage collector in Go implements a concurrent, non-generational (non-generational) method based on the Mark-and-Sweep algorithm with a heap size trigger.

Main principles of operation:

  1. Trigger activation: The collector starts when the memory allocated by the program exceeds a certain threshold. This threshold is dynamically adjusted.
  2. Mark Phase:
    • The collector pauses only the critical part of the Mark Phase (Stop-the-World, STW), but this takes very little time.
    • Concurrently with the running program (mutator), the collector traverses the object graph from root pointers (registers, global variables, goroutine stacks).
    • Reachable (live) objects are marked as used.
  3. Sweep Phase:
    • After completing the Mark Phase, the collector traverses the list of memory spans.
    • Unmarked objects are considered garbage, and their memory is freed.
    • This phase is also performed concurrently with the program's operation.
  4. Write Barrier: Go uses a write barrier to track changes in the object graph during the parallel marking phase. This ensures the collector works correctly despite memory modifications by the mutator.
  5. No generations: Unlike some other languages, Go does not divide objects into generations. The collector processes the entire heap as a whole.
  6. Low latency goal: The design of Go GC aimed to minimize pauses caused by garbage collection (STW pauses), making it suitable for server applications.

Concurrency and the use of write barriers allow the collector to minimize program stop times, ensuring high performance.

An example of simplified memory management (not directly GC, but illustrating resource release):

package main

import (
	"fmt"
	"os"
)

func main() {
	// Example of creating a temporary resource that will be cleaned up
	file, err := os.Create("temp.txt")
	if err != nil {
		fmt.Println("Error creating file:", err)
		return
	}
	// Deferred file closing.
	// Although this is not GC in the pure sense, it demonstrates resource release.
	defer file.Close()

	fmt.Println("File 'temp.txt' created.")

	// The program can now work with the file...

	// GC runs automatically in the background to collect unused objects in the heap.
	// For example, creating a slice or map:
	data := make([]int, 1000000) // Allocation in heap
	_ = data // Usage

	// When data becomes unreachable (e.g., when exiting the function),
	// the garbage collector will eventually free the memory allocated for it.
}