]> Cypherpunks repositories - gostls13.git/commitdiff
strings: use Builder in Repeat to avoid an allocation
authorgo101 <tapir.liu@gmail.com>
Wed, 22 Aug 2018 16:12:46 +0000 (16:12 +0000)
committerBrad Fitzpatrick <bradfitz@golang.org>
Wed, 22 Aug 2018 16:40:21 +0000 (16:40 +0000)
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: 4b2c73f3bfa0b3789268b9ea6e1ecdb984e8087c
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>
src/strings/strings.go
src/strings/strings_test.go

index 97d83cfde1110444c7a5531961529f5f4cdde91d..e0bebced63f847a34959f7599741bca88f4e7167 100644 (file)
@@ -523,23 +523,33 @@ func Map(mapping func(rune) rune, s string) string {
 // It panics if count is negative or if
 // the result of (len(s) * count) overflows.
 func Repeat(s string, count int) string {
+       if count == 0 {
+               return ""
+       }
+
        // Since we cannot return an error on overflow,
        // we should panic if the repeat will generate
        // an overflow.
        // See Issue golang.org/issue/16237
        if count < 0 {
                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")
        }
 
-       b := make([]byte, len(s)*count)
-       bp := copy(b, s)
-       for bp < len(b) {
-               copy(b[bp:], b[:bp])
-               bp *= 2
+       n := len(s) * count
+       var b Builder
+       b.Grow(n)
+       b.WriteString(s)
+       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.
index bb46e136f26bcf7ae5a81ee6d848076e294d05eb..d6197ed895e8bf8c4847bf1915d63e4f6b7d1749 100644 (file)
@@ -1660,8 +1660,15 @@ func BenchmarkSplitNMultiByteSeparator(b *testing.B) {
 }
 
 func BenchmarkRepeat(b *testing.B) {
-       for i := 0; i < b.N; i++ {
-               Repeat("-", 80)
+       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++ {
+                                       Repeat(s[:n], c)
+                               }
+                       })
+               }
        }
 }