]> Cypherpunks repositories - gostls13.git/commitdiff
bytes, strings: improve EqualFold fast version for ASCII
authorEric Pauley <eric@pauley.me>
Sun, 29 Apr 2018 04:15:03 +0000 (00:15 -0400)
committerBrad Fitzpatrick <bradfitz@golang.org>
Tue, 1 May 2018 18:52:19 +0000 (18:52 +0000)
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>
src/bytes/bytes.go
src/strings/strings.go
src/strings/strings_test.go

index 32bf6ab30d32dcee31ae001352a0c61a8621811d..437a6e12df867049c9c251a99e9a09925f9d637d 100644 (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
index b0a53fdefdfee8668a101b64d04cce9fa06dbe1c..45345e008888e27246b2f4412211192d4bf27cb2 100644 (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
index d8fcb62a87709defa563f36ebdf5b7b0292a973f..876f06c67482b96886363fed9ae968900c4aba30 100644 (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