bytes, strings: add ASCII fast path to EqualFold

This commit adds an ASCII fast path to bytes/strings EqualFold that
roughly doubles performance when all characters are ASCII.

It also changes strings.EqualFold to use `for range` for the first
string since this is ~10% faster than using utf8.DecodeRuneInString for
both (see #31666).

Performance (similar results on arm64 and amd64):

name                        old time/op  new time/op  delta
EqualFold/Tests-10           238ns ± 0%   172ns ± 1%  -27.91%  (p=0.000 n=10+10)
EqualFold/ASCII-10          20.5ns ± 0%   9.7ns ± 0%  -52.73%  (p=0.000 n=10+10)
EqualFold/UnicodePrefix-10  86.5ns ± 0%  77.6ns ± 0%  -10.37%  (p=0.000 n=10+10)
EqualFold/UnicodeSuffix-10  86.8ns ± 2%  71.3ns ± 0%  -17.88%  (p=0.000 n=10+8)

Change-Id: I058f3f97a08dc04d65af895674d85420f920abe1
Reviewed-on: https://go-review.googlesource.com/c/go/+/425459
Reviewed-by: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
Charlie Vieth 2022-08-24 14:23:28 -04:00 committed by Gopher Robot
parent 9c916c7901
commit c70fd4b30a
3 changed files with 97 additions and 15 deletions

View file

@ -1556,13 +1556,36 @@ 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")
b.Run("Tests", func(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")
}
}
}
}
})
const s1 = "abcdefghijKz"
const s2 = "abcDefGhijKz"
b.Run("ASCII", func(b *testing.B) {
for i := 0; i < b.N; i++ {
EqualFold(s1, s2)
}
})
b.Run("UnicodePrefix", func(b *testing.B) {
for i := 0; i < b.N; i++ {
EqualFold("αβδ"+s1, "ΑΒΔ"+s2)
}
})
b.Run("UnicodeSuffix", func(b *testing.B) {
for i := 0; i < b.N; i++ {
EqualFold(s1+"αβδ", s2+"ΑΒΔ")
}
})
}
var CountTests = []struct {