diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go index 1871814c6e00d5..72ccdfc98eb512 100644 --- a/src/bytes/bytes.go +++ b/src/bytes/bytes.go @@ -1330,6 +1330,12 @@ func Index(s, sep []byte) int { // // Cut returns slices of the original slice s, not copies. func Cut(s, sep []byte) (before, after []byte, found bool) { + if len(sep) == 1 { + if i := IndexByte(s, sep[0]); i >= 0 { + return s[:i], s[i+1:], true + } + return s, nil, false + } if i := Index(s, sep); i >= 0 { return s[:i], s[i+len(sep):], true } diff --git a/src/bytes/bytes_test.go b/src/bytes/bytes_test.go index 5e8cf85fd90ab9..e800a2f51e9e69 100644 --- a/src/bytes/bytes_test.go +++ b/src/bytes/bytes_test.go @@ -2263,3 +2263,21 @@ func TestClone(t *testing.T) { } } } + +func BenchmarkCut(b *testing.B) { + b.ReportAllocs() + + for _, skip := range [...]int{2, 4, 8, 16, 32, 64} { + s := Repeat(append(append(Repeat([]byte(" "), skip), 'a', 'a'), Repeat([]byte(" "), skip)...), 1<<16/skip) + b.Run(fmt.Sprintf("Cut-One/%d", skip), func(b *testing.B) { + for i := 0; i < b.N; i++ { + _, _, _ = Cut(s, []byte{'a'}) + } + }) + b.Run(fmt.Sprintf("Cut-Two/%d", skip), func(b *testing.B) { + for i := 0; i < b.N; i++ { + _, _, _ = Cut(s, []byte{'a', 'a'}) + } + }) + } +} diff --git a/src/strings/strings.go b/src/strings/strings.go index f53ae1f9a785a3..fdd5eda97ecba1 100644 --- a/src/strings/strings.go +++ b/src/strings/strings.go @@ -1309,9 +1309,16 @@ func Index(s, substr string) int { // The found result reports whether sep appears in s. // If sep does not appear in s, cut returns s, "", false. func Cut(s, sep string) (before, after string, found bool) { + if len(sep) == 1 { + if i := IndexByte(s, sep[0]); i >= 0 { + return s[:i], s[i+1:], true + } + return s, "", false + } if i := Index(s, sep); i >= 0 { return s[:i], s[i+len(sep):], true } + return s, "", false } diff --git a/src/strings/strings_test.go b/src/strings/strings_test.go index ac493c7dcd43b0..2d2f64165d599f 100644 --- a/src/strings/strings_test.go +++ b/src/strings/strings_test.go @@ -2071,3 +2071,21 @@ func BenchmarkReplaceAll(b *testing.B) { stringSink = ReplaceAll("banana", "a", "<>") } } + +func BenchmarkCut(b *testing.B) { + b.ReportAllocs() + + for _, skip := range [...]int{2, 4, 8, 16, 32, 64} { + s := Repeat(Repeat(" ", skip)+"aa"+Repeat(" ", skip), 1<<16/skip) + b.Run(fmt.Sprintf("Cut-One/%d", skip), func(b *testing.B) { + for i := 0; i < b.N; i++ { + _, _, _ = Cut(s, "a") + } + }) + b.Run(fmt.Sprintf("Cut-Two/%d", skip), func(b *testing.B) { + for i := 0; i < b.N; i++ { + _, _, _ = Cut(s, "aa") + } + }) + } +}