Understanding Go's Garbage Collection: Model, Phases, and Latency Optimization
This article explains Go's garbage collection mechanism, describing its Mark‑Sweep model, the three collection phases, latency implications, and practical tips for reducing pause times through memory‑pressure reduction and runtime debugging tools.
Garbage Collection (GC) is the process of automatically reclaiming memory that is no longer in use; because memory is finite, variables must release their allocated space when they become unreachable.
In Go, GC runs in a background daemon thread, automatically tracking object lifetimes without direct programmer intervention.
Go employs a Mark‑Sweep algorithm, organized into three stages:
Mark Setup – Stop‑The‑World (STW)
Marking – Concurrent
Mark Termination – STW
STW (Stop‑The‑World) pauses all goroutines while the GC performs critical operations, which can introduce latency.
1. Mark Setup – STW
The GC starts by enabling the Write Barrier, which requires all running goroutines to pause briefly (typically 10–30 µs). If a goroutine never reaches a safe point (e.g., it loops endlessly), the GC cannot proceed, leading to increased pause times—a problem slated for optimization in Go 1.14.
If a goroutine fails to pause, the GC remains blocked, causing latency to grow.
Once the Write Barrier is active, the GC proceeds to the next stage.
2. Marking – Concurrent
During this phase, the GC marks live objects concurrently with application code, consuming about 25 % of a CPU core. If the workload is heavy, a Mark Assist helper can be activated to share the marking work.
3. Mark Termination – STW
After marking finishes, the Write Barrier is disabled, cleanup tasks run, and the next GC target is calculated. This stage also requires STW, typically lasting 60–90 µs.
When GC completes, goroutines resume execution.
Sweeping – Concurrent
After collection, the Sweeping phase reclaims memory marked as unused. This work occurs when the runtime allocates new memory, and its latency adds to allocation cost.
Latency Optimization
Although Go's GC is efficient, pause times can still affect applications. Reducing memory pressure—e.g., avoiding frequent slice reallocations—helps lower GC latency. See the article “Go Development Ten Common Mistakes” for details.
Debugging and Profiling
Enable GC tracing to observe phase timings: GODEBUG=gctrace=1 Metrics reveal the duration of each stage, as illustrated below:
Additionally, use pprof for deeper performance analysis (refer to external resources for usage).
References:
https://www.ardanlabs.com/blog/2018/12/garbage-collection-in-go-part1-semantics.html
https://www.ardanlabs.com/blog/2019/05/garbage-collection-in-go-part2-gctraces.html
https://www.ardanlabs.com/blog/2019/07/garbage-collection-in-go-part3-gcpacing.html
System Architect Go
Programming, architecture, application development, message queues, middleware, databases, containerization, big data, image processing, machine learning, AI, personal growth.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
