Sobes.tech
Senior

How is garbage collection implemented in Go and what trade-offs does it make between latency and throughput?

sobes.tech AI

Answer from AI

The garbage collector (GC) in Go is implemented as a three-phase, concurrent, low-latency garbage collector based on a tri-color marking algorithm and incremental sweeping.

Main features:

  • Concurrency: GC runs in parallel with the main application, minimizing pauses.
  • Three-phase algorithm: includes marking, scanning, and sweeping phases.
  • Incrementality: garbage collection is broken into small steps to avoid long pauses.

Trade-offs between latency and throughput:

  • Go GC is focused on minimizing delays (low latency) so that the application does not stop for long, which is important for server and interactive applications.
  • This is achieved through more frequent but shorter pauses, which can slightly reduce overall throughput due to overhead from frequent collections.
  • Go developers constantly balance these parameters, improving algorithms to reduce pauses without significantly harming performance.

Example: in Go 1.8 and above, GC can keep pauses around milliseconds, which is significantly better compared to earlier versions.

// Example of a simple program demonstrating GC operation
package main

import (
	"fmt"
	"runtime"
)

func main() {
	var m runtime.MemStats
	runtime.ReadMemStats(&m)
	fmt.Printf("Before allocation: Alloc = %v MiB\n", m.Alloc/1024/1024)

	// Creating many objects
	for i := 0; i < 1e6; i++ {
		_ = make([]byte, 1024) // 1KB
	}

	runtime.GC() // Explicit call to garbage collector
	runtime.ReadMemStats(&m)
	fmt.Printf("After GC: Alloc = %v MiB\n", m.Alloc/1024/1024)
}