Commit 39fcf8bf authored by Erik Dubbelboer's avatar Erik Dubbelboer Committed by Brad Fitzpatrick

net: use bytes.Equal instead of bytesEqual

bytes.Equal is written in assembly and is slightly faster than the
current Go bytesEqual from the net package.

benchcmp:
benchmark                 old ns/op     new ns/op     delta
BenchmarkIPCompare4-8     7.74          7.01          -9.43%
BenchmarkIPCompare6-8     8.47          6.86          -19.01%

Change-Id: I2a7ad35867489b46f0943aef5776a2fe1b46e2df
Reviewed-on: https://go-review.googlesource.com/36850Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 61bf0d1c
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
package net package net
import _ "unsafe" // for go:linkname
// IP address lengths (bytes). // IP address lengths (bytes).
const ( const (
IPv4len = 4 IPv4len = 4
...@@ -381,17 +383,9 @@ func (ip IP) Equal(x IP) bool { ...@@ -381,17 +383,9 @@ func (ip IP) Equal(x IP) bool {
return false return false
} }
func bytesEqual(x, y []byte) bool { // bytes.Equal is implemented in runtime/asm_$goarch.s
if len(x) != len(y) { //go:linkname bytesEqual bytes.Equal
return false func bytesEqual(x, y []byte) bool
}
for i, b := range x {
if y[i] != b {
return false
}
}
return true
}
func (ip IP) matchAddrFamily(x IP) bool { func (ip IP) matchAddrFamily(x IP) bool {
return ip.To4() != nil && x.To4() != nil || ip.To16() != nil && ip.To4() == nil && x.To16() != nil && x.To4() == nil return ip.To4() != nil && x.To4() != nil || ip.To16() != nil && ip.To4() == nil && x.To16() != nil && x.To4() == nil
......
...@@ -6,6 +6,7 @@ package net ...@@ -6,6 +6,7 @@ package net
import ( import (
"bytes" "bytes"
"math/rand"
"reflect" "reflect"
"runtime" "runtime"
"testing" "testing"
...@@ -645,3 +646,32 @@ func TestIPAddrScope(t *testing.T) { ...@@ -645,3 +646,32 @@ func TestIPAddrScope(t *testing.T) {
} }
} }
} }
func BenchmarkIPEqual(b *testing.B) {
b.Run("IPv4", func(b *testing.B) {
benchmarkIPEqual(b, IPv4len)
})
b.Run("IPv6", func(b *testing.B) {
benchmarkIPEqual(b, IPv6len)
})
}
func benchmarkIPEqual(b *testing.B, size int) {
ips := make([]IP, 1000)
for i := range ips {
ips[i] = make(IP, size)
rand.Read(ips[i])
}
// Half of the N are equal.
for i := 0; i < b.N/2; i++ {
x := ips[i%len(ips)]
y := ips[i%len(ips)]
x.Equal(y)
}
// The other half are not equal.
for i := 0; i < b.N/2; i++ {
x := ips[i%len(ips)]
y := ips[(i+1)%len(ips)]
x.Equal(y)
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment