mirror of
https://github.com/golang/go
synced 2024-11-23 07:20:06 -07:00
strings: make IndexRune faster
re-implement IndexRune by Index which is well optimized to get performance gain. name old time/op new time/op delta IndexRune-4 30.2ns ± 1% 28.3ns ± 1% -6.22% (p=0.000 n=20+19) IndexRuneLongString-4 156ns ± 1% 49ns ± 1% -68.72% (p=0.000 n=19+19) IndexRuneFastPath-4 10.6ns ± 2% 10.0ns ± 1% -6.30% (p=0.000 n=18+18) Change-Id: Ie663b8f7860ca51892dd4be182fca3caa5f8ae61 Reviewed-on: https://go-review.googlesource.com/28546 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
a4bdd64555
commit
8737dac1f2
@ -176,17 +176,11 @@ func LastIndex(s, sep string) int {
|
||||
// IndexRune returns the index of the first instance of the Unicode code point
|
||||
// r, or -1 if rune is not present in s.
|
||||
func IndexRune(s string, r rune) int {
|
||||
switch {
|
||||
case r < utf8.RuneSelf:
|
||||
if r < utf8.RuneSelf {
|
||||
return IndexByte(s, byte(r))
|
||||
default:
|
||||
for i, c := range s {
|
||||
if c == r {
|
||||
return i
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1
|
||||
|
||||
return Index(s, string(r))
|
||||
}
|
||||
|
||||
// IndexAny returns the index of the first instance of any Unicode code point
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
package strings
|
||||
|
||||
//go:noescape
|
||||
|
||||
// indexShortStr returns the index of the first instance of c in s, or -1 if c is not present in s.
|
||||
// indexShortStr requires 2 <= len(c) <= shortStringLen
|
||||
func indexShortStr(s, c string) int // ../runtime/asm_$GOARCH.s
|
||||
|
@ -244,6 +244,20 @@ func TestIndexRune(t *testing.T) {
|
||||
t.Errorf("IndexRune(%q,%d)= %v; want %v", test.s, test.rune, actual, test.out)
|
||||
}
|
||||
}
|
||||
|
||||
haystack := "test世界"
|
||||
allocs := testing.AllocsPerRun(1000, func() {
|
||||
if i := IndexRune(haystack, 's'); i != 2 {
|
||||
t.Fatalf("'s' at %d; want 2", i)
|
||||
}
|
||||
if i := IndexRune(haystack, '世'); i != 4 {
|
||||
t.Fatalf("'世' at %d; want 4", i)
|
||||
}
|
||||
})
|
||||
|
||||
if allocs != 0 {
|
||||
t.Errorf(`expected no allocations, got %f`, allocs)
|
||||
}
|
||||
}
|
||||
|
||||
const benchmarkString = "some_text=some☺value"
|
||||
@ -257,6 +271,17 @@ func BenchmarkIndexRune(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
var benchmarkLongString = Repeat(" ", 100) + benchmarkString
|
||||
|
||||
func BenchmarkIndexRuneLongString(b *testing.B) {
|
||||
if got := IndexRune(benchmarkLongString, '☺'); got != 114 {
|
||||
b.Fatalf("wrong index: expected 114, got=%d", got)
|
||||
}
|
||||
for i := 0; i < b.N; i++ {
|
||||
IndexRune(benchmarkLongString, '☺')
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexRuneFastPath(b *testing.B) {
|
||||
if got := IndexRune(benchmarkString, 'v'); got != 17 {
|
||||
b.Fatalf("wrong index: expected 17, got=%d", got)
|
||||
|
Loading…
Reference in New Issue
Block a user