Subtests & Sub-benchmarks in Go1.7

Table-driven benchmarking

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,