Go: bytes.Equal vs. reflect.DeepEqual (vs. self-implemented equal) (https://wang.yuxuan.org/blog/item/2017/02/comparing-byte-s-in-go)
package main_test | |
import ( | |
"bytes" | |
"fmt" | |
"math/rand" | |
"os" | |
"reflect" | |
"testing" | |
"time" | |
) | |
var sizes = []int{ | |
1024, | |
1024 * 1024, | |
64 * 1024 * 1024, | |
} | |
func TestMain(m *testing.M) { | |
rand.Seed(time.Now().Unix()) | |
os.Exit(m.Run()) | |
} | |
func BenchmarkEqual(b *testing.B) { | |
for _, size := range sizes { | |
b1 := make([]byte, size) | |
rand.Read(b1) | |
b2 := make([]byte, size) | |
copy(b2, b1) | |
b.Run( | |
fmt.Sprintf("reflect.DeepEqual-%d", size), | |
func(b *testing.B) { | |
for i := 0; i < b.N; i++ { | |
reflect.DeepEqual(b1, b2) | |
} | |
}, | |
) | |
b.Run( | |
fmt.Sprintf("equal-%d", size), | |
func(b *testing.B) { | |
for i := 0; i < b.N; i++ { | |
equal(b1, b2) | |
} | |
}, | |
) | |
b.Run( | |
fmt.Sprintf("bytes.Equal-%d", size), | |
func(b *testing.B) { | |
for i := 0; i < b.N; i++ { | |
bytes.Equal(b1, b2) | |
} | |
}, | |
) | |
} | |
} | |
func BenchmarkNonEqual(b *testing.B) { | |
for _, size := range sizes { | |
b1 := make([]byte, size) | |
rand.Read(b1) | |
b2 := make([]byte, size) | |
rand.Read(b2) | |
b.Run( | |
fmt.Sprintf("reflect.DeepEqual-%d", size), | |
func(b *testing.B) { | |
for i := 0; i < b.N; i++ { | |
reflect.DeepEqual(b1, b2) | |
} | |
}, | |
) | |
b.Run( | |
fmt.Sprintf("equal-%d", size), | |
func(b *testing.B) { | |
for i := 0; i < b.N; i++ { | |
equal(b1, b2) | |
} | |
}, | |
) | |
b.Run( | |
fmt.Sprintf("bytes.Equal-%d", size), | |
func(b *testing.B) { | |
for i := 0; i < b.N; i++ { | |
bytes.Equal(b1, b2) | |
} | |
}, | |
) | |
} | |
} | |
func TestEqual(t *testing.T) { | |
for _, size := range sizes { | |
b1 := make([]byte, size) | |
rand.Read(b1) | |
b2 := make([]byte, size) | |
rand.Read(b2) | |
b3 := make([]byte, size) | |
copy(b3, b1) | |
t.Run( | |
fmt.Sprintf("reflect.DeepEqual-%d", size), | |
func(t *testing.T) { | |
if reflect.DeepEqual(b1, b2) { | |
t.Error("reflect.DeepEqual(b1, b2) should return false") | |
} | |
if !reflect.DeepEqual(b1, b3) { | |
t.Error("reflect.DeepEqual(b1, b2) should return true") | |
} | |
}, | |
) | |
t.Run( | |
fmt.Sprintf("equal-%d", size), | |
func(t *testing.T) { | |
if equal(b1, b2) { | |
t.Error("equal(b1, b2) should return false") | |
} | |
if !equal(b1, b3) { | |
t.Error("equal(b1, b2) should return true") | |
} | |
}, | |
) | |
t.Run( | |
fmt.Sprintf("bytes.Equal-%d", size), | |
func(t *testing.T) { | |
if bytes.Equal(b1, b2) { | |
t.Error("bytes.Equal(b1, b2) should return false") | |
} | |
if !bytes.Equal(b1, b3) { | |
t.Error("bytes.Equal(b1, b2) should return true") | |
} | |
}, | |
) | |
} | |
} | |
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 | |
} |
$ go test -bench=. | |
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 | |
PASS | |
ok _/Users/fishy/work/test 44.270s |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment