What do the block and mutex profiles measure, how do you enable them, and how do they differ?
Question 373HardGo 1.22 to 1.25
Both are disabled by default because they add overhead.
- Block profile: where goroutines waited on synchronization primitives — channel send/recv,
select,sync.Mutex,sync.Cond,WaitGroup.Wait. Records total delay per stack. Enabled withruntime.SetBlockProfileRate(ns): sample on average one blocking event per ns nanoseconds blocked;1= record everything. - Mutex profile: contention on
sync.Mutex/RWMutex, attributed to the stack of the goroutine that held the lock and delayed others (reported at Unlock). Enabled withruntime.SetMutexProfileFraction(n): report ~1/n contention events.
func main() {
runtime.SetBlockProfileRate(10_000) // ~ one sample per 10µs blocked
runtime.SetMutexProfileFraction(100) // 1% of contention events
startDebugServer()
// ...
}
// go tool pprof http://127.0.0.1:6060/debug/pprof/mutex
// go tool pprof http://127.0.0.1:6060/debug/pprof/block
Key distinction: block answers "where are my goroutines waiting?" (the victims); mutex answers "which critical section is causing the waiting?" (the culprit). Gotcha: the block profile includes intentional waiting (a worker idling on <-jobs), so filter with -focus. Neither shows time blocked in syscalls/network I/O — for that use the execution trace. In benchmarks: go test -bench=. -blockprofile=b.out -mutexprofile=m.out.
More on Performance, Profiling & Testing
- Q371Explain inuse_space vs alloc_space in a heap profile. Which do you use to find a memory leak vs GC pressure?
- Q372How would you detect and diagnose a goroutine leak?
- Q374When would you use go tool trace instead of pprof? What can it show that profiles cannot?
- Q375What is testing.B.Loop (Go 1.24) and why is it preferred over the classic b.N loop?
- Q376What does this benchmark report, and why is it wrong?
- Q377How do you run benchmarks rigorously and compare two implementations? Explain -benchmem, ReportAllocs, and benchstat.