skip to content
Alvin Lucillo

Multiple data size benchmarking

/ 3 min read

It’s also important to know how different sizes of data processed by the function affect benchmark matrics. In the code below, different sizes of the event message are tested. It’s expected the higher the size of the data being processed, the poorer the metrics can appear. But since we are comparing the two encoding methods, binary encoding appears better compared to JSON encoding even as the data size grows. However, at large data, they almost have the same amount of allocated heap bytes per event at 1MiB data size. It might be because they are basically doing the same amount of memory allocation, but the binary encoding is still better in a lot of marks, especially the processing speed.

func BenchmarkEncodeJSON(b *testing.B) {
	for _, size := range encodingMessageSizes {
		b.Run(size.name, func(b *testing.B) {
			event := Event{ID: 42, Message: strings.Repeat("x", size.bytes)}

			var data []byte
			var err error
			b.ReportAllocs()
			b.SetBytes(int64(len(event.Message)))

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

func BenchmarkEncodeBinary(b *testing.B) {
	for _, size := range encodingMessageSizes {
		b.Run(size.name, func(b *testing.B) {
			event := Event{ID: 42, Message: strings.Repeat("x", size.bytes)}

			var data []byte
			b.ReportAllocs()
			b.SetBytes(int64(len(event.Message)))

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

// Names become part of the benchmark output, for example:
// BenchmarkEncodeJSON/4KiB and BenchmarkEncodeBinary/4KiB.
var encodingMessageSizes = []struct {
	name  string
	bytes int
}{
	{name: "16B", bytes: 16},
	{name: "256B", bytes: 256},
	{name: "4KiB", bytes: 4 * 1024},
	{name: "64KiB", bytes: 64 * 1024},
	{name: "500KiB", bytes: 500 * 1024},
	{name: "1MiB", bytes: 1024 * 1024},
}

In the result below, we can see that binary encoding uses less allocation resources. Binary encoding uses less bytes and less number of allocation per event.

go test -run '^$' -bench '^BenchmarkEncode'
goos: linux
goarch: arm64
pkg: codec01
BenchmarkEncodeJSON/16B-12       8947384               134.8 ns/op       118.73 MB/s          72 B/op          2 allocs/op
BenchmarkEncodeJSON/256B-12      2839560               424.5 ns/op       603.09 MB/s         312 B/op          2 allocs/op
BenchmarkEncodeJSON/4KiB-12       230463              4525 ns/op         905.18 MB/s        4891 B/op          2 allocs/op
BenchmarkEncodeJSON/64KiB-12               17946             66241 ns/op         989.36 MB/s       73908 B/op          2 allocs/op
BenchmarkEncodeJSON/500KiB-12               2280            498207 ns/op        1027.69 MB/s      528684 B/op          2 allocs/op
BenchmarkEncodeJSON/1MiB-12                 1027           1118344 ns/op         937.62 MB/s     1100548 B/op          2 allocs/op
BenchmarkEncodeBinary/16B-12            61868744                20.79 ns/op      769.77 MB/s          24 B/op          1 allocs/op
BenchmarkEncodeBinary/256B-12            8737191               134.8 ns/op      1899.02 MB/s         288 B/op          1 allocs/op
BenchmarkEncodeBinary/4KiB-12             929598              1307 ns/op        3134.14 MB/s        4864 B/op          1 allocs/op
BenchmarkEncodeBinary/64KiB-12             73698             15598 ns/op        4201.69 MB/s       73728 B/op          1 allocs/op
BenchmarkEncodeBinary/500KiB-12            13584             87922 ns/op        5823.37 MB/s      516097 B/op          1 allocs/op
BenchmarkEncodeBinary/1MiB-12               7465            159647 ns/op        6568.08 MB/s     1056769 B/op          1 allocs/op
PASS
ok      codec01 14.164s