1
0
mirror of https://github.com/golang/go synced 2024-11-18 12:34:42 -07:00

bytes, strings: improve EqualFold fast version for ASCII

The existing implementation only considers the special ASCII
case when the lower character is an upper case letter. This
means that most ASCII comparisons use unicode.SimpleFold even
when it is not necessary.

benchmark                old ns/op     new ns/op     delta
BenchmarkEqualFold-8     450           390           -13.33%

Change-Id: I735ca3c30fc0145c186d2a54f31fd39caab2c3fa
Reviewed-on: https://go-review.googlesource.com/110018
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Eric Pauley 2018-04-29 00:15:03 -04:00 committed by Brad Fitzpatrick
parent a5b80d469a
commit 9d11c63b64
3 changed files with 18 additions and 6 deletions

View File

@ -805,9 +805,9 @@ func EqualFold(s, t []byte) bool {
tr, sr = sr, tr
}
// Fast check for ASCII.
if tr < utf8.RuneSelf && 'A' <= sr && sr <= 'Z' {
// ASCII, and sr is upper case. tr must be lower case.
if tr == sr+'a'-'A' {
if tr < utf8.RuneSelf {
// ASCII only, sr/tr must be upper/lower case
if 'A' <= sr && sr <= 'Z' && tr == sr+'a'-'A' {
continue
}
return false

View File

@ -908,9 +908,9 @@ func EqualFold(s, t string) bool {
tr, sr = sr, tr
}
// Fast check for ASCII.
if tr < utf8.RuneSelf && 'A' <= sr && sr <= 'Z' {
// ASCII, and sr is upper case. tr must be lower case.
if tr == sr+'a'-'A' {
if tr < utf8.RuneSelf {
// ASCII only, sr/tr must be upper/lower case
if 'A' <= sr && sr <= 'Z' && tr == sr+'a'-'A' {
continue
}
return false

View File

@ -1379,6 +1379,8 @@ var EqualFoldTests = []struct {
{"abcdefghijK", "abcdefghij\u212A", true},
{"abcdefghijkz", "abcdefghij\u212Ay", false},
{"abcdefghijKz", "abcdefghij\u212Ay", false},
{"1", "2", false},
{"utf-8", "US-ASCII", false},
}
func TestEqualFold(t *testing.T) {
@ -1392,6 +1394,16 @@ func TestEqualFold(t *testing.T) {
}
}
func BenchmarkEqualFold(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, tt := range EqualFoldTests {
if out := EqualFold(tt.s, tt.t); out != tt.out {
b.Fatal("wrong result")
}
}
}
}
var CountTests = []struct {
s, sep string
num int