tezvyn:

Go's GC: Low-Latency Collection with Tri-color Marking

AI-drafted, machine-checkedSource: go.devadvanced

Go's GC uses a tri-color algorithm to find unused memory concurrently, avoiding long pauses. It's crucial for low-latency services. The main footgun is breaking the invariant: a 'finished' (black) object must never point to a new (white) one without notifying…

WHY IT EXISTS: Traditional garbage collectors often freeze an application to find and clean up memory, causing unpredictable 'stop-the-world' pauses. For modern, high-concurrency services, these pauses kill latency. Go needed a GC that could work alongside the application, not against it, to achieve consistently low latency.

THE MENTAL MODEL: Think of Go's GC as a search party exploring a graph of connected objects. It uses three colors to track progress: white for undiscovered objects, grey for discovered but not yet scanned objects, and black for objects that have been fully scanned and are confirmed to be alive. The goal is to find everything reachable from the application's starting points.

HOW IT WORKS: At the start of a GC cycle, all objects are white. The collector finds all 'roots'—objects directly accessible by the app like globals and stack variables—and colors them grey. It then repeats a process: pick a grey object, color it black, and scan it for pointers. If it finds a pointer to a white object, it colors that object grey, adding it to the 'to-do' list. This continues until no grey objects are left. Any object still white is unreachable garbage and can be reclaimed. This all happens concurrently while the application (the 'mutator') is running. To prevent the mutator from hiding a live object by pointing a black object to a white one, a 'write barrier' intercepts pointer modifications. The barrier ensures the newly-pointed-to white object is colored grey, guaranteeing the GC will eventually scan it.

WHEN TO USE IT: This isn't a library you choose; it is the fundamental memory management model of the Go runtime. Every Go program uses it to manage heap allocations, making Go suitable for network servers and other systems where low, predictable latency is a primary requirement.

WHEN NOT TO USE IT: You cannot disable it in Go. However, the design prioritizes low latency over maximum throughput. For some offline batch processing jobs where total execution time is the only metric and pauses don't matter, a different GC strategy might be theoretically more efficient, but this is not Go's target domain.

ONE CANONICAL EXAMPLE: An HTTP server handles thousands of requests per second, each allocating objects. The tri-color GC runs in the background, cleaning up objects from finished requests. Because it runs concurrently and only pauses for very short, well-defined periods, the server can maintain low p99 latencies even under heavy load, which would be impossible with a classic stop-the-world collector.

Read the original → go.dev

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.