From 86ee89225aea2326fd50dbeb233cfc622413a4cf Mon Sep 17 00:00:00 2001 From: Ignacio Hagopian Date: Tue, 17 Aug 2021 23:52:00 +0000 Subject: [PATCH] strings: smarter growth of temporal buffer and avoid copying on return MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 TryBot-Result: Go Bot Reviewed-by: Ian Lance Taylor Trust: Robert Griesemer --- src/strings/replace.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/strings/replace.go b/src/strings/replace.go index e28d428879..ee728bb22b 100644 --- a/src/strings/replace.go +++ b/src/strings/replace.go @@ -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) { -- 2.48.1