How do you use ResetTimer, StopTimer, and RunParallel in Go benchmarks?
Tests Go benchmark timer hygiene and parallel execution. A strong answer covers b.StopTimer before setup, b.ResetTimer before the loop, and b.RunParallel for CPU-bound scaling. A red flag is resetting without stopping or using parallel benchmarks for I/O.
WHAT THIS TESTS: Whether you understand that Go benchmarks measure total elapsed time and heap allocations by default, including setup and teardown, and whether you know how to isolate the code under test. It also checks if you understand the difference between sequential and parallel benchmarks and when parallel execution provides meaningful signal versus noise.
A GOOD ANSWER COVERS: Four things in order. First, b.StopTimer pauses the benchmark clock and memory allocation counters before expensive setup such as building large fixtures or seeding random state. Second, b.ResetTimer zeros the elapsed time and allocation counters so the measurement starts clean immediately before the loop; this is critical because b.N may be large and setup costs would otherwise dominate. Third, b.StartTimer resumes measurement if you stopped it earlier, though many candidates simply call b.ResetTimer after setup which implicitly starts timing. Fourth, b.RunParallel is appropriate only for CPU-bound or lock-contention workloads where you want to see how the function scales with GOMAXPROCS; it spins up goroutines that each call the body function and uses sync.Pool or local variables to avoid false sharing.
COMMON WRONG ANSWERS: Calling b.ResetTimer without b.StopTimer first, which still counts setup time if it occurs before the reset. Using b.RunParallel for I/O-bound or network-bound functions, which creates goroutine thrashing and measures scheduler latency rather than code efficiency. Forgetting that b.ResetTimer also resets allocation counters, leading to misleading allocs-per-op numbers. Another red flag is manually spawning goroutines inside a normal benchmark instead of using b.RunParallel, because the benchmark runner cannot correctly attribute work or adjust b.N.
LIKELY FOLLOW-UPS: How does b.RunParallel differ from manually calling runtime.GOMAXPROCS? What happens to allocation metrics if you only call b.StopTimer but never reset? How would you benchmark a function that mutates global state and needs isolation between iterations? When should you prefer b.Loop over manual b.N loops in newer Go versions?
ONE CONCRETE EXAMPLE: Suppose you are benchmarking a JSON serializer. Before the loop you allocate a large nested struct. You call b.StopTimer, build the struct, then call b.ResetTimer. Inside the loop you only call json.Marshal. If the serializer uses a sync.Pool for buffers, you use b.RunParallel to measure whether pool contention rises under concurrency; the body function receives a pointer to testing.PB and calls pb.Next() in its loop. You would not use RunParallel if the benchmark writes to a single bytes.Buffer because the mutex would dominate and hide the serializer's real cost.
Read the original → pkg.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.