Skip to content

Commit e3ed0fb

Browse files
1911860538gopherbot
authored andcommitted
all: replace strings.Split with strings.SplitSeq
In Go 1.25+, strings.SplitSeq offers better performance. Here are the benchmark results comparing strings.Split and strings.SplitSeq in a for-loop, with the benchmark code located in src/strings/iter_test.go: goos: darwin goarch: amd64 pkg: cmd/go/internal/auth cpu: Intel(R) Core(TM) i7-8569U CPU @ 2.80GHz │ old.txt │ new.txt │ │ sec/op │ sec/op vs base │ ParseGitAuth/standard-8 281.4n ± 1% 218.0n ± 11% -22.54% (p=0.000 n=10) ParseGitAuth/with_url-8 549.1n ± 1% 480.5n ± 13% -12.48% (p=0.002 n=10) ParseGitAuth/minimal-8 235.4n ± 1% 197.3n ± 7% -16.20% (p=0.000 n=10) ParseGitAuth/complex-8 797.6n ± 2% 805.2n ± 4% ~ (p=0.481 n=10) ParseGitAuth/empty-8 87.48n ± 3% 63.25n ± 6% -27.71% (p=0.000 n=10) ParseGitAuth/malformed-8 228.8n ± 1% 171.2n ± 3% -25.17% (p=0.000 n=10) geomean 288.9n 237.7n -17.72% │ old.txt │ new.txt │ │ B/op │ B/op vs base │ ParseGitAuth/standard-8 192.00 ± 0% 96.00 ± 0% -50.00% (p=0.000 n=10) ParseGitAuth/with_url-8 400.0 ± 0% 288.0 ± 0% -28.00% (p=0.000 n=10) ParseGitAuth/minimal-8 144.00 ± 0% 80.00 ± 0% -44.44% (p=0.000 n=10) ParseGitAuth/complex-8 528.0 ± 0% 400.0 ± 0% -24.24% (p=0.000 n=10) ParseGitAuth/empty-8 32.00 ± 0% 16.00 ± 0% -50.00% (p=0.000 n=10) ParseGitAuth/malformed-8 176.00 ± 0% 80.00 ± 0% -54.55% (p=0.000 n=10) geomean 179.0 102.1 -42.96% │ old.txt │ new.txt │ │ allocs/op │ allocs/op vs base │ ParseGitAuth/standard-8 3.000 ± 0% 2.000 ± 0% -33.33% (p=0.000 n=10) ParseGitAuth/with_url-8 4.000 ± 0% 3.000 ± 0% -25.00% (p=0.000 n=10) ParseGitAuth/minimal-8 3.000 ± 0% 2.000 ± 0% -33.33% (p=0.000 n=10) ParseGitAuth/complex-8 4.000 ± 0% 3.000 ± 0% -25.00% (p=0.000 n=10) ParseGitAuth/empty-8 2.000 ± 0% 1.000 ± 0% -50.00% (p=0.000 n=10) ParseGitAuth/malformed-8 3.000 ± 0% 2.000 ± 0% -33.33% (p=0.000 n=10) geomean 3.086 2.040 -33.91% Updates #69315. Change-Id: Id0219edea45d9658d527b863162ebe917e7821d9 GitHub-Last-Rev: 392b315 GitHub-Pull-Request: #75259 Reviewed-on: https://go-review.googlesource.com/c/go/+/701015 Reviewed-by: Keith Randall <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Michael Knyszek <[email protected]> Reviewed-by: Emmanuel Odeke <[email protected]> Reviewed-by: Keith Randall <[email protected]> Auto-Submit: Emmanuel Odeke <[email protected]>
1 parent 10bfddc commit e3ed0fb

File tree

39 files changed

+178
-50
lines changed

39 files changed

+178
-50
lines changed

misc/ios/go_ios_exec.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ func copyLocalData(dstbase string) (pkgpath string, err error) {
212212
// Copy all immediate files and testdata directories between
213213
// the package being tested and the source root.
214214
pkgpath = ""
215-
for _, element := range strings.Split(finalPkgpath, string(filepath.Separator)) {
215+
for element := range strings.SplitSeq(finalPkgpath, string(filepath.Separator)) {
216216
if debug {
217217
log.Printf("copying %s", pkgpath)
218218
}

src/cmd/cgo/gcc.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ func (f *File) loadDefines(gccOptions []string) bool {
251251
stdout := gccDefines(b.Bytes(), gccOptions)
252252

253253
var gccIsClang bool
254-
for _, line := range strings.Split(stdout, "\n") {
254+
for line := range strings.SplitSeq(stdout, "\n") {
255255
if len(line) < 9 || line[0:7] != "#define" {
256256
continue
257257
}
@@ -428,7 +428,7 @@ func (p *Package) guessKinds(f *File) []*Name {
428428
notDeclared
429429
)
430430
sawUnmatchedErrors := false
431-
for _, line := range strings.Split(stderr, "\n") {
431+
for line := range strings.SplitSeq(stderr, "\n") {
432432
// Ignore warnings and random comments, with one
433433
// exception: newer GCC versions will sometimes emit
434434
// an error on a macro #define with a note referring

src/cmd/cgo/internal/test/testx.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ func issue7978check(t *testing.T, wantFunc string, badFunc string, depth int) {
447447
runtime.GC()
448448
buf := make([]byte, 65536)
449449
trace := string(buf[:runtime.Stack(buf, true)])
450-
for _, goroutine := range strings.Split(trace, "\n\n") {
450+
for goroutine := range strings.SplitSeq(trace, "\n\n") {
451451
if strings.Contains(goroutine, "test.issue7978go") {
452452
trace := strings.Split(goroutine, "\n")
453453
// look for the expected function in the stack

src/cmd/compile/internal/base/flag.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ func readEmbedCfg(file string) {
570570

571571
// parseSpectre parses the spectre configuration from the string s.
572572
func parseSpectre(s string) {
573-
for _, f := range strings.Split(s, ",") {
573+
for f := range strings.SplitSeq(s, ",") {
574574
f = strings.TrimSpace(f)
575575
switch f {
576576
default:

src/cmd/dist/build.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ func findgoversion() string {
380380
if i := strings.Index(b, "\n"); i >= 0 {
381381
rest := b[i+1:]
382382
b = chomp(b[:i])
383-
for _, line := range strings.Split(rest, "\n") {
383+
for line := range strings.SplitSeq(rest, "\n") {
384384
f := strings.Fields(line)
385385
if len(f) == 0 {
386386
continue
@@ -1137,7 +1137,7 @@ func shouldbuild(file, pkg string) bool {
11371137
}
11381138

11391139
// Check file contents for //go:build lines.
1140-
for _, p := range strings.Split(readfile(file), "\n") {
1140+
for p := range strings.SplitSeq(readfile(file), "\n") {
11411141
p = strings.TrimSpace(p)
11421142
if p == "" {
11431143
continue
@@ -2016,7 +2016,7 @@ func cmdlist() {
20162016
}
20172017

20182018
func setNoOpt() {
2019-
for _, gcflag := range strings.Split(gogcflags, " ") {
2019+
for gcflag := range strings.SplitSeq(gogcflags, " ") {
20202020
if gcflag == "-N" || gcflag == "-l" {
20212021
noOpt = true
20222022
break

src/cmd/distpack/pack.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ func readVERSION(goroot string) (version string, t time.Time) {
271271
log.Fatal(err)
272272
}
273273
version, rest, _ := strings.Cut(string(data), "\n")
274-
for _, line := range strings.Split(rest, "\n") {
274+
for line := range strings.SplitSeq(rest, "\n") {
275275
f := strings.Fields(line)
276276
if len(f) == 0 {
277277
continue

src/cmd/fix/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,14 @@ func main() {
8484

8585
if *allowedRewrites != "" {
8686
allowed = make(map[string]bool)
87-
for _, f := range strings.Split(*allowedRewrites, ",") {
87+
for f := range strings.SplitSeq(*allowedRewrites, ",") {
8888
allowed[f] = true
8989
}
9090
}
9191

9292
if *forceRewrites != "" {
9393
force = make(map[string]bool)
94-
for _, f := range strings.Split(*forceRewrites, ",") {
94+
for f := range strings.SplitSeq(*forceRewrites, ",") {
9595
force[f] = true
9696
}
9797
}

src/cmd/go/internal/auth/gitauth.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func runGitAuth(client *http.Client, dir, url string) (string, http.Header, erro
8282
// Any of these values may be empty if parsing fails.
8383
func parseGitAuth(data []byte) (parsedPrefix, username, password string) {
8484
prefix := new(url.URL)
85-
for _, line := range strings.Split(string(data), "\n") {
85+
for line := range strings.SplitSeq(string(data), "\n") {
8686
key, value, ok := strings.Cut(strings.TrimSpace(line), "=")
8787
if !ok {
8888
continue

src/cmd/go/internal/auth/gitauth_test.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package auth
66

77
import (
8+
"strings"
89
"testing"
910
)
1011

@@ -82,3 +83,77 @@ password:secr3t
8283
}
8384
}
8485
}
86+
87+
func BenchmarkParseGitAuth(b *testing.B) {
88+
// Define different test scenarios to benchmark
89+
testCases := []struct {
90+
name string
91+
data []byte
92+
}{{
93+
// Standard scenario with all basic fields present
94+
name: "standard",
95+
data: []byte(`
96+
protocol=https
97+
host=example.com
98+
username=bob
99+
password=secr3t
100+
`),
101+
}, {
102+
// Scenario with URL field included
103+
name: "with_url",
104+
data: []byte(`
105+
protocol=https
106+
host=example.com
107+
username=bob
108+
password=secr3t
109+
url=https://example.com/repo
110+
`),
111+
}, {
112+
// Minimal scenario with only required fields
113+
name: "minimal",
114+
data: []byte(`
115+
protocol=https
116+
host=example.com
117+
`),
118+
}, {
119+
// Complex scenario with longer values and extra fields
120+
name: "complex",
121+
data: func() []byte {
122+
var builder strings.Builder
123+
builder.WriteString("protocol=https\n")
124+
builder.WriteString("host=example.com\n")
125+
builder.WriteString("username=longusernamenamename\n")
126+
builder.WriteString("password=longpasswordwithmanycharacters123456789\n")
127+
builder.WriteString("url=https://example.com/very/long/path/to/repository\n")
128+
builder.WriteString("extra1=value1\n")
129+
builder.WriteString("extra2=value2\n")
130+
return []byte(builder.String())
131+
}(),
132+
}, {
133+
// Scenario with empty input
134+
name: "empty",
135+
data: []byte(``),
136+
}, {
137+
// Scenario with malformed input (using colon instead of equals)
138+
name: "malformed",
139+
data: []byte(`
140+
protocol:https
141+
host:example.com
142+
username:bob
143+
password:secr3t
144+
`),
145+
}}
146+
147+
for _, tc := range testCases {
148+
b.Run(tc.name, func(b *testing.B) {
149+
b.ResetTimer()
150+
for b.Loop() {
151+
prefix, username, password := parseGitAuth(tc.data)
152+
153+
_ = prefix
154+
_ = username
155+
_ = password
156+
}
157+
})
158+
}
159+
}

src/cmd/go/internal/auth/netrc.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func parseNetrc(data string) []netrcLine {
2424
var nrc []netrcLine
2525
var l netrcLine
2626
inMacro := false
27-
for _, line := range strings.Split(data, "\n") {
27+
for line := range strings.SplitSeq(data, "\n") {
2828
if inMacro {
2929
if line == "" {
3030
inMacro = false

0 commit comments

Comments
 (0)