Golang - Garbage Collection in General
Go is a statically typed, garbage collected language, much like Java, Python, or C#. In this blog, we’ll dive deeper into how Go manages memory and what happens during a garbage collection cycle.
What is Garbage Collection and Why is it needed?
In programming, garbage refers to allocated memory space that is no longer reachable or usable by the program.
When a program executes, it primarily uses two parts of memory: the Stack and the Heap.
type RandomBox struct {
ID int
Name string
}
func GenerateRandomBox() *RandomBox {
// 'ref' is allocated on the stack
// The struct itself escapes to the heap
ref := &RandomBox{ID: 1, Name: "Rust"}
return ref
}
func main() {
box := GenerateRandomBox()
fmt.Println(box.Name)
}
Go uses Escape Analysis to determine whether a variable can stay on the stack or must “escape” to the heap. When a reference to heap memory is lost, that memory becomes garbage and must be cleaned up.

The Go Garbage Collector
Go uses a concurrent mark and sweep garbage collector. It is called concurrent because it can run in parallel with your main application code, minimizing pauses.
The GC Phases
When the compiler decides it’s time to run a collection cycle, it follows these steps:
1. Mark Setup (STW) The collector initiates a Stop The World (STW) event. This briefly pauses all goroutines to enable the write barrier, ensuring that no data is lost or corrupted while the collector is working.

2. Marking (Concurrent) In this phase:
- The collector inspects stacks to find root pointers into the heap.
- It traverses the heap to identify objects currently in use.
- The collector uses 25% of available CPU power (e.g., 1 out of 4 threads).
Mark Assist: If an application goroutine is allocating memory faster than the collector can mark it, the collector may recruit that goroutine to help with the marking process.

3. Mark Termination (STW) Another brief STW event occurs to turn off the write barrier, perform final cleanup, and calculate the schedule for the next GC run. The goal is to keep these STW pauses under 100ms.
Sweeping and Triggers
Sweeping is the process of reclaiming memory from objects that were not marked as being in use. Interestingly, sweeping happens outside the main GC cycle—typically when a new memory allocation is requested—so it doesn’t add to the GC latency.

What triggers a GC run?
- Heap Growth: By default, GC runs when the heap doubles in size from the previous run.
- Time Interval: If a collection hasn’t run for more than two minutes, one is forced.
- Manual Trigger: You can call
runtime.GC()manually (though rarely recommended). - Allocation Threshold: Large allocations in
runtime.mallocgccan also trigger a run.
Tuning the Collector
Go’s philosophy is to keep tuning simple. Developers have one primary knob: the GOGC environment variable (or debug.SetGCPercent). The default is 100, meaning GC triggers when the heap grows by 100%.

The GC Pacer
The GC Pacer algorithm continuously monitors the application and may start a collection earlier than scheduled if it determines that doing so will provide a better performance benefit.