Go

What is a write barrier and which one does Go use?

Question 337HardGo 1.22 to 1.25

A write barrier is a small piece of code the compiler inserts around pointer writes into heap memory. It runs only while the GC is marking; otherwise it is skipped by a cheap check along the lines of if writeBarrier.enabled. It tells the collector about pointer changes so the tri-color invariant still holds.

Since Go 1.8 the runtime uses a hybrid write barrier that combines:

  • Yuasa deletion barrier: shade the old pointer being overwritten.
  • Dijkstra insertion barrier: shade the new pointer being written.
// conceptual pseudo-code of *slot = ptr during marking
func writePointer(slot *unsafe.Pointer, ptr unsafe.Pointer) {
    shade(*slot) // deletion (Yuasa)
    shade(ptr)   // insertion (Dijkstra)
    *slot = ptr
}

Why the hybrid matters: stack writes have no barrier, because putting one on every local assignment would be far too expensive. With a Dijkstra-only barrier, Go 1.5 through 1.7 had to re-scan all stacks during a stop-the-world mark termination, which caused pauses of tens of milliseconds. The hybrid barrier lets each stack be scanned once and blackened, and it removed that re-scan. That change is why pauses dropped below a millisecond.

Gotcha: the barrier also makes pointer-heavy code slower during GC cycles. That is one more reason to prefer pointer-free data such as []int or struct values over []*T in hot structures.

More on Memory, GC & Runtime Internals

All 38 Memory, GC & Runtime Internals questions