Comparing []byte's in Go
As I'm new to Go, I think it's quite understandable that I'm not familiar with the standard library yet, and reinvented the wheel sometimes.
One day I need to compare two []byte's. Since I'm not aware of any implementation in standard library, and this is simple enough, I wrote my own comparing function. It's something like:
func equal(b1, b2 []byte) bool {
if len(b1) != len(b2) {
return false
}
for i, b := range b1 {
if b != b2[i] {
return false
}
}
return true
}
A few days later, I saw my colleague used reflect.DeepEqual in our codebase. I thought "Oh that's cool! No need to reinvent the wheel!" So I removed my own implementation and used reflect.DeepEqual instead.
A few more days later, I accidentally discovered the existence of bytes.Equal. This is obviously faster than reflect.DeepEqual (because its feature is much simpler), so I'm going to replace them. But before that, I decided to do a simple benchmark test to see how much faster.
(In case you are not familiar with Go or Go's testing package, Go provided a very easy to use benchmark framework in it. Some might think the lack of features like Assume makes the testing code mouthful. I kind of agree with that, but I'm also mostly OK with that.)
The full benchmark test code can be found in this public gist. I'll just post the result here
BenchmarkEqual/reflect.DeepEqual-1024-4 20000 91193 ns/op BenchmarkEqual/equal-1024-4 3000000 544 ns/op BenchmarkEqual/bytes.Equal-1024-4 50000000 22.6 ns/op BenchmarkEqual/reflect.DeepEqual-1048576-4 20 89556304 ns/op BenchmarkEqual/equal-1048576-4 3000 536891 ns/op BenchmarkEqual/bytes.Equal-1048576-4 30000 44613 ns/op BenchmarkEqual/reflect.DeepEqual-67108864-4 1 5801186044 ns/op BenchmarkEqual/equal-67108864-4 30 37011544 ns/op BenchmarkEqual/bytes.Equal-67108864-4 200 8574768 ns/op BenchmarkNonEqual/reflect.DeepEqual-1024-4 5000000 280 ns/op BenchmarkNonEqual/equal-1024-4 500000000 3.46 ns/op BenchmarkNonEqual/bytes.Equal-1024-4 300000000 4.56 ns/op BenchmarkNonEqual/reflect.DeepEqual-1048576-4 5000000 272 ns/op BenchmarkNonEqual/equal-1048576-4 500000000 3.44 ns/op BenchmarkNonEqual/bytes.Equal-1048576-4 300000000 4.52 ns/op BenchmarkNonEqual/reflect.DeepEqual-67108864-4 5000000 269 ns/op BenchmarkNonEqual/equal-67108864-4 500000000 3.42 ns/op BenchmarkNonEqual/bytes.Equal-67108864-4 300000000 4.50 ns/op
In short, bytes.Equal is usually 3 orders of magnitude faster than reflect.DeepEqual when the result is true, and 2 orders of magnitude faster when the result is false. (Also, my own implementation is only 1 order of magnitude slower than bytes.Equal when the result is true, and slightly faster when the result is false :)
And of course I replaced reflect.DeepEqual with bytes.Equal in our code base as appropriate.