Subtests & Sub-benchmarks in Go1.7
In Go1.7, `testing` package will supports subtests and sub-benchmarks. With this feature, you can define tests/benchmarks in a test/benchmark function. It’s easy to create hierarchical tests or table-driven sub-benchmarks. It also provides a way to share common setup and tear-down code.
This feature may have less benefits on tests because normally table-driven tests is enough. It will improve your benchmarks codes a lot.
Let me show some sample codes. For example, when you want to take benchmark of function `Foo` with different configuration, before Go1.7, you need to prepare functions for each configuration.
// you need to prepare functions for each bench mark setting
func BenchmarkFoo1(b *testing.B) { benchFoo(b, 1) }
func BenchmarkFoo10(b *testing.B) { benchFoo(b, 10) }
func BenchmarkFoo100(b *testing.B) { benchFoo(b, 100) }// helper function to run Foo with different config
func benchFoo(b *testing.B, config int) {
for i := 0; i < b.N; i++ {
Foo(base)
}
If you use Sub-benchmarks feature in Go1.7, you can write this benchmark like the following.
func BenchmarkFoo(b *testing.B) {
cases := []struct {
Config int
}{
{Config: 1},
{Config: 10},
{Config: 100},
} for _, bc := range cases {
b.Run(fmt.Sprintf(“%d”, bc.Config), func(b *testing.B) { benchFoo(b, bc.Base) })
}
}
You can use table-driven approach! It’s simple and easy to read (Benchmark name will be Top level function name + first argument of `Run` method. e.g., `BenchmarkFoo/1`, `BenchmarkFoo/2`… )
If you check standard library changes in Go1.7, you can see it benefits from sub-benchmarks a lot. The followings are some of examples,