Writing bechmarks for your Go code is quite simple since all required features are already baked into the standard library. Very similar to writing tests where you use the *testing.T pointer you use *testing.B for benchmarks. However benchmarks are usually a snapshot of the current situation. They are done once when implementing an important function but they do not run during continuous integration (CI). As a new developer joining an existing team you don't know which code is critical for performance and you don't know if your changes have influence on those benchmarks. In this post we will show you how to set up benchmarks that run in your CI and how to monitor their values over time. So you cannot worsen those benchmarks by accident.

Let's take a look at our demo repository github.com/seriesci/bench with a very simple function.

package bench import "time" func Efficient ( a , b int ) int { time . Sleep ( 500 * time . Nanosecond ) return a + b }

For this dummy function we would like to add a benchmark.

package bench import "testing" func BenchmarkEfficient ( b * testing . B ) { for n := 0 ; n < b . N ; n ++ { Efficient ( 1 , 2 ) } }

Now you are able to run the following command to see the benchmark on the command line.

$ go test -bench = . goos: linux goarch: amd64 BenchmarkEfficient-8 71128 20363 ns/op PASS ok seriesci/bench 2 .637s

We're only interested in the highlighted line and especially in the final value 20363 ns/op . We have to filter out this relevant information and send it to seriesci to continuously track the value. We're using grep to get the right line starting with BenchmarkEfficient... and awk to get the right column. The whole line consists of four columns where the value is the third one. That is where '{print $3}' is coming from.

$ go test -bench = . | grep BenchmarkEfficient | awk '{print $3 }' 20363

That's great. Now we simply take this value and post it to the seriesci API via curl . We're using xargs and its replstr feature to put the final value into the correct position. ${TOKEN} and ${CIRCLE_SHA1} are environment variables which are available during CI. ${TOKEN} has to be set manually whereas ${CIRCLE_SHA1} is automatically available.

$ go test -bench = . | grep BenchmarkEfficient | awk '{print $3 }' | xargs -I { } curl \ --header "Authorization: Token ${TOKEN} " \ --data value = "{}" \ --data sha = " ${CIRCLE_SHA1} " \ https://seriesci.com/api/repos/seriesci/bench/benchmark/values