1
0
mirror of https://github.com/golang/go synced 2024-11-14 08:30:25 -07:00

strings: use Builder in Repeat to avoid an allocation

name           old time/op    new time/op    delta
Repeat/5x1-4     95.9ns ± 2%    70.1ns ± 2%  -26.93%  (p=0.000 n=9+10)
Repeat/5x2-4      146ns ± 3%     100ns ± 2%  -31.99%  (p=0.000 n=10+10)
Repeat/5x6-4      203ns ± 3%     140ns ± 4%  -30.77%  (p=0.000 n=10+10)
Repeat/10x1-4     139ns ± 3%      92ns ± 4%  -34.08%  (p=0.000 n=10+10)
Repeat/10x2-4     188ns ± 4%     122ns ± 2%  -35.34%  (p=0.000 n=10+10)
Repeat/10x6-4     264ns ± 5%     179ns ± 4%  -32.15%  (p=0.000 n=10+10)

name           old alloc/op   new alloc/op   delta
Repeat/5x1-4      10.0B ± 0%      5.0B ± 0%  -50.00%  (p=0.000 n=10+10)
Repeat/5x2-4      32.0B ± 0%     16.0B ± 0%  -50.00%  (p=0.000 n=10+10)
Repeat/5x6-4      64.0B ± 0%     32.0B ± 0%  -50.00%  (p=0.000 n=10+10)
Repeat/10x1-4     32.0B ± 0%     16.0B ± 0%  -50.00%  (p=0.000 n=10+10)
Repeat/10x2-4     64.0B ± 0%     32.0B ± 0%  -50.00%  (p=0.000 n=10+10)
Repeat/10x6-4      128B ± 0%       64B ± 0%  -50.00%  (p=0.000 n=10+10)

Change-Id: I6619336da636df39c560f6cc481519f48c6e8176
GitHub-Last-Rev: 4b2c73f3bf
GitHub-Pull-Request: golang/go#25894
Reviewed-on: https://go-review.googlesource.com/118855
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
go101 2018-08-22 16:12:46 +00:00 committed by Brad Fitzpatrick
parent 6a11e1e8db
commit 7a178df0bc
2 changed files with 26 additions and 9 deletions

View File

@ -523,23 +523,33 @@ func Map(mapping func(rune) rune, s string) string {
// It panics if count is negative or if // It panics if count is negative or if
// the result of (len(s) * count) overflows. // the result of (len(s) * count) overflows.
func Repeat(s string, count int) string { func Repeat(s string, count int) string {
if count == 0 {
return ""
}
// Since we cannot return an error on overflow, // Since we cannot return an error on overflow,
// we should panic if the repeat will generate // we should panic if the repeat will generate
// an overflow. // an overflow.
// See Issue golang.org/issue/16237 // See Issue golang.org/issue/16237
if count < 0 { if count < 0 {
panic("strings: negative Repeat count") panic("strings: negative Repeat count")
} else if count > 0 && len(s)*count/count != len(s) { } else if len(s)*count/count != len(s) {
panic("strings: Repeat count causes overflow") panic("strings: Repeat count causes overflow")
} }
b := make([]byte, len(s)*count) n := len(s) * count
bp := copy(b, s) var b Builder
for bp < len(b) { b.Grow(n)
copy(b[bp:], b[:bp]) b.WriteString(s)
bp *= 2 for b.Len() < n {
if b.Len() <= n/2 {
b.WriteString(b.String())
} else {
b.WriteString(b.String()[:n-b.Len()])
break
} }
return string(b) }
return b.String()
} }
// ToUpper returns a copy of the string s with all Unicode letters mapped to their upper case. // ToUpper returns a copy of the string s with all Unicode letters mapped to their upper case.

View File

@ -1660,8 +1660,15 @@ func BenchmarkSplitNMultiByteSeparator(b *testing.B) {
} }
func BenchmarkRepeat(b *testing.B) { func BenchmarkRepeat(b *testing.B) {
s := "0123456789"
for _, n := range []int{5, 10} {
for _, c := range []int{1, 2, 6} {
b.Run(fmt.Sprintf("%dx%d", n, c), func(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
Repeat("-", 80) Repeat(s[:n], c)
}
})
}
} }
} }