Benchmarks
Benchmarking is another useful feature of the golang testing
standard library. It allows us to conduct performance tests for the parts of our code where being fast matters most. That will help us ensure that we don't cause performance regressions when we are making changes.
Benchmarks are very similar to tests. If you replace Test
with Benchmark
and testing.T
with testing.B
, you're 90% of the way there.
The other 10% is that you'll need to write a for loop around whatever you're trying to benchmark. testing.B
provides a parameter, N
, which determines the number of loops to do over the benchmarked function. A very short benchmarking function might look like this:
func BenchmarkEmptyFunc(b *testing.B) {
for i := 0; i < b.N; i++ {
func() {}()
}
}
Let's set up a Get
benchmark since the Get
function is a very critical path in a key-value store. We want it to be fast and remain fast in the future.
In order to make our benchmark we're going to copy the entirety of our TestGet
method and make some small changes. BenchmarkGet
will look exactly like TestGet
, except we remove the t.Parallel()
call, rename the function to BenchmarkGet
, and change t *testing.T
to b *testing.B
.
The reason we are copying TestGet
rather than coming up with a common set of abstractions and using them in both functions, is because we actually expect these functions to differ greatly over time. TestGet
will likely receive a large number of varried test cases, some added as bugs are discovered and some added to help ensure the function will work as intended with new keys and values. BenchmarkGet
, however, is likely to remain very stable, and will only need to be adjusted for significant changes made to the Get
function. So copying everything allows us to more easily write BenchmarkGet
while preventing a tight coupling of these two functions that are currently similar but will likely be very different in the future.
This page is a preview of Reliable Webservers with Go