Can we run a go test benchmark in Parallel? The short answer is Yes
. This article will show how.
What I mean by running a benchmark in parallel is that the function that we benchmark is called multiple times at the same time. If you have never done a benchmark in Go, check out this post.
Non-parallel benchmark
By default, a go test benchmark is not run in parallel, it runs sequentially. Let’s see some examples. Suppose we have a function below.
func MyFunc() {
log.Println("MyFunc start")
time.Sleep(200 * time.Millisecond)
log.Println("MyFunc end")
}
The function just sleeps for 200 milliseconds, and logs at the beginning and end for testing.
Then we run a benchmark with the code below in the test file.
func BenchmarkMyFunc(b *testing.B) {
for i := 0; i < b.N; i++ {
MyFunc()
}
}
We run the benchmark and see the logs.
go test -bench BenchmarkMyFunc ./...
Below is the result log.
2023/09/09 05:03:20 MyFunc start
2023/09/09 05:03:20 MyFunc end
2023/09/09 05:03:20 MyFunc start
2023/09/09 05:03:20 MyFunc end
2023/09/09 05:03:20 MyFunc start
2023/09/09 05:03:20 MyFunc end
...
We can see that the function is run in sequence. The test calls the function and waits for the function to end before calling it again.
Parallel benchmark
What if we want it to be called in parallel? Maybe to simulate the real usage of the function or to test a mutex or other purpose.
We can use the following benchmark code to run the benchmark in parallel. We use RunParallel
method of testing.B
to do it.
RunParallel runs a benchmark in parallel.
It creates multiple goroutines and distributes b.N iterations among them.
The number of goroutines defaults to GOMAXPROCS. To increase parallelism for non-CPU-bound benchmarks, call SetParallelism before RunParallel.
func BenchmarkParallelMyFunc(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
MyFunc()
}
})
}
Run the benchmark and see the logs.
go test -bench BenchmarkParallelMyFunc ./...
2023/09/09 05:04:50 MyFunc start
2023/09/09 05:04:50 MyFunc start
2023/09/09 05:04:50 MyFunc start
2023/09/09 05:04:50 MyFunc end
2023/09/09 05:04:50 MyFunc end
2023/09/09 05:04:50 MyFunc end
...
From the logs, we can see that the function was called in parallel, multiple times at the same time.