strings: Map: avoid allocation when string is unchanged

This speeds up strings.ToLower, etc.

before/after:
strings_test.BenchmarkMapNoChanges 1000000 1013 ns/op
strings_test.BenchmarkMapNoChanges 5000000  442 ns/op

R=r, rog, eh, rsc
CC=golang-dev
https://golang.org/cl/4306056
This commit is contained in:
Brad Fitzpatrick 2011-03-28 09:41:57 -07:00
parent 43512e6c70
commit a7a854b82f
2 changed files with 37 additions and 2 deletions

View file

@ -312,9 +312,19 @@ func Map(mapping func(rune int) int, s string) string {
// fine. It could also shrink but that falls out naturally.
maxbytes := len(s) // length of b
nbytes := 0 // number of bytes encoded in b
b := make([]byte, maxbytes)
for _, c := range s {
// The output buffer b is initialized on demand, the first
// time a character differs.
var b []byte
for i, c := range s {
rune := mapping(c)
if b == nil {
if rune == c {
continue
}
b = make([]byte, maxbytes)
nbytes = copy(b, s[:i])
}
if rune >= 0 {
wid := 1
if rune >= utf8.RuneSelf {
@ -330,6 +340,9 @@ func Map(mapping func(rune int) int, s string) string {
nbytes += utf8.EncodeRune(b[nbytes:maxbytes], rune)
}
}
if b == nil {
return s
}
return string(b[0:nbytes])
}