Last active
March 30, 2019 01:09
-
-
Save fishy/bca72d0d65ba35e9ab6b50f66f9fc42e to your computer and use it in GitHub Desktop.
Go: bytes.Equal vs. reflect.DeepEqual (vs. self-implemented equal) (https://wang.yuxuan.org/blog/item/2017/02/comparing-byte-s-in-go)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ 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