diff --git a/src/strings/strings.go b/src/strings/strings.go index 5f244d6e20..88fbeecc6f 100644 --- a/src/strings/strings.go +++ b/src/strings/strings.go @@ -379,25 +379,29 @@ func FieldsFunc(s string, f func(rune) bool) []string { spans := make([]span, 0, 32) // Find the field start and end indices. - wasField := false - fromIndex := 0 - for i, rune := range s { + // Doing this in a separate pass (rather than slicing the string s + // and collecting the result substrings right away) is significantly + // more efficient, possibly due to cache effects. + start := -1 // valid span start if >= 0 + for end, rune := range s { if f(rune) { - if wasField { - spans = append(spans, span{start: fromIndex, end: i}) - wasField = false + if start >= 0 { + spans = append(spans, span{start, end}) + // Set start to a negative value. + // Note: using -1 here consistently and reproducibly + // slows down this code by a several percent on amd64. + start = ^start } } else { - if !wasField { - fromIndex = i - wasField = true + if start < 0 { + start = end } } } // Last field might end at EOF. - if wasField { - spans = append(spans, span{fromIndex, len(s)}) + if start >= 0 { + spans = append(spans, span{start, len(s)}) } // Create strings from recorded field indices.