skip to content
Alvin Lucillo

Stat benchmark summary with benchstat

/ 2 min read

To make more sense of the benchmark comparisons, we can use benchstat. In the BenchmarkEncode test, we specified two formats: json and binary.

func BenchmarkEncode(b *testing.B) {
	b.Run("format=json", benchmarkEncodeJSON)
	b.Run("format=binary", benchmarkEncodeBinary)
}

func benchmarkEncodeJSON(b *testing.B) {
	var data []byte
	var err error
	b.ReportAllocs()
	b.SetBytes(int64(len(benchmarkEvent.Message)))

	for b.Loop() {
		data, err = EncodeJSON(benchmarkEvent)
		if err != nil {
			b.Fatal(err)
		}
	}
	sinkBytes = data
}

func benchmarkEncodeBinary(b *testing.B) {
	var data []byte
	b.ReportAllocs()
	b.SetBytes(int64(len(benchmarkEvent.Message)))

	for b.Loop() {
		data = EncodeBinary(benchmarkEvent)
	}
	sinkBytes = data
}

func EncodeJSON(event Event) ([]byte, error) {
	return json.Marshal(event)
}

func DecodeJSON(data []byte) (Event, error) {
	var event Event
	err := json.Unmarshal(data, &event)
	return event, err
}

func EncodeBinary(event Event) []byte {
	data := make([]byte, 8+len(event.Message))
	binary.BigEndian.PutUint64(data[:8], event.ID)
	copy(data[8:], event.Message)
	return data
}

We run the benchmark test function 10 times and output the result to a file. The result is similar to the usual benchmark result; nothing new here. What’s new is the use of benchstat. Here, we provide the file to that tool with specific column and row.

The statistical summary shows that json is the baseline and shows the average values and how they differ with the binary results. The summary shows that there are significant improvements with binary encoding.

go test -run '^$' -bench '^BenchmarkEncode$' \
  -count=10 > /tmp/codec01-encode.txt

benchstat -col /format -row .name /tmp/codec01-encode.txt
goos: linux
goarch: arm64
pkg: codec01
       │     json     │               binary                │
       │    sec/op    │   sec/op     vs base                │
Encode   150.35n ± 1%   30.23n ± 3%  -79.89% (p=0.000 n=10)

       │     json     │                 binary                 │
       │     B/s      │      B/s       vs base                 │
Encode   310.9Mi ± 1%   1545.8Mi ± 3%  +397.26% (p=0.000 n=10)

       │    json     │               binary               │
       │    B/op     │    B/op     vs base                │
Encode   104.00 ± 0%   64.00 ± 0%  -38.46% (p=0.000 n=10)

       │    json    │               binary               │
       │ allocs/op  │ allocs/op   vs base                │
Encode   2.000 ± 0%   1.000 ± 0%  -50.00% (p=0.000 n=10)