Go

Walk through the phases of a GC cycle. Where are the stop-the-world pauses?

Question 338HardGo 1.22 to 1.25
  1. Sweep termination (STW, microseconds): finish sweeping the previous cycle, reach a safe point on every P, and enable the write barrier.
  2. Concurrent mark: the world restarts. Dedicated background workers take about 25% of GOMAXPROCS. Idle Ps help, and allocating goroutines do mark assists. Each goroutine stack is scanned by briefly stopping only that goroutine.
  3. Mark termination (STW, microseconds): drain the remaining work, disable the write barrier, and compute the next heap goal.
  4. Concurrent sweep: spans are swept lazily when allocation needs them, plus by a background sweeper.

Since goroutine preemption became asynchronous (signal-based, Go 1.14), a tight loop with no function calls can no longer hold up a STW for a long time.

Where latency really comes from: usually not the STW pauses but mark assists. An allocation-heavy request goroutine can be made to do GC work, which inflates its tail latency. The GC also takes 25% or more of the CPU while it is marking. In GODEBUG=gctrace=1 output, check the assist share of the mark CPU time.

What the interviewer is looking for: the two short pauses, that everything else is concurrent, and that the real cost is CPU and assists rather than pause time.

More on Memory, GC & Runtime Internals

All 38 Memory, GC & Runtime Internals questions