]> Cypherpunks repositories - gostls13.git/commitdiff
strings: smarter growth of temporal buffer and avoid copying on return
authorIgnacio Hagopian <jsign.uy@gmail.com>
Tue, 17 Aug 2021 23:52:00 +0000 (23:52 +0000)
committerRobert Griesemer <gri@golang.org>
Sun, 22 Aug 2021 23:49:55 +0000 (23:49 +0000)
The implementation for single strings had two optimization opportunities:
1. Grow the temporary buffer by known size before appending.
2. Avoid a full copy of the result since the underlying buffer won't be mutated afterward.
Both things were leveraged by using a Builder instead of a byte slice.

Relevant benchmark results:

        name           old time/op    new time/op    delta
        SingleMatch-8    32.0µs ± 3%    26.1µs ± 3%  -18.41%  (p=0.000 n=9+10)

        name           old speed      new speed      delta
        SingleMatch-8   469MB/s ± 3%   574MB/s ± 3%  +22.56%  (p=0.000 n=9+10)

        name           old alloc/op   new alloc/op   delta
        SingleMatch-8    81.3kB ± 0%    49.0kB ± 0%  -39.67%  (p=0.000 n=10+10)

        name           old allocs/op  new allocs/op  delta
        SingleMatch-8      19.0 ± 0%      11.0 ± 0%  -42.11%  (p=0.000 n=10+10)

Change-Id: I23af56a15875206c0ff4ce29a51bec95fd48bb11
GitHub-Last-Rev: 403cfc3c2794b5da27792c51999417a2a052b365
GitHub-Pull-Request: golang/go#47766
Reviewed-on: https://go-review.googlesource.com/c/go/+/343089
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Trust: Robert Griesemer <gri@golang.org>

src/strings/replace.go

index e28d42887930b9d852bdd2129c28f4ebf3bd8c8b..ee728bb22b655259247ad7b871ae9983b28fac72 100644 (file)
@@ -387,7 +387,7 @@ func makeSingleStringReplacer(pattern string, value string) *singleStringReplace
 }
 
 func (r *singleStringReplacer) Replace(s string) string {
-       var buf []byte
+       var buf Builder
        i, matched := 0, false
        for {
                match := r.finder.next(s[i:])
@@ -395,15 +395,16 @@ func (r *singleStringReplacer) Replace(s string) string {
                        break
                }
                matched = true
-               buf = append(buf, s[i:i+match]...)
-               buf = append(buf, r.value...)
+               buf.Grow(match + len(r.value))
+               buf.WriteString(s[i : i+match])
+               buf.WriteString(r.value)
                i += match + len(r.finder.pattern)
        }
        if !matched {
                return s
        }
-       buf = append(buf, s[i:]...)
-       return string(buf)
+       buf.WriteString(s[i:])
+       return buf.String()
 }
 
 func (r *singleStringReplacer) WriteString(w io.Writer, s string) (n int, err error) {