1
0
mirror of https://github.com/golang/go synced 2024-11-23 19:50:06 -07:00

all: remove unnecessary allocations from w.WriteString(fmt.Sprint*(...)) by fmt.Fprint*(w, ...)

Noticed in a manual audit from a customer codebase that the pattern

    w.WriteString(fmt.Sprint*(args...))

was less efficient and in most cases we can just invoke:

    fmt.Fprint*(w, args...)

and from the simple benchmarks we can see quick wins in all dimensions:

$ benchstat before.txt after.txt
name            old time/op    new time/op    delta
DetailString-8    5.48µs ±23%    4.40µs ±11%  -19.79%  (p=0.000 n=20+17)

name            old alloc/op   new alloc/op   delta
DetailString-8    2.63kB ± 0%    2.11kB ± 0%  -19.76%  (p=0.000 n=20+20)

name            old allocs/op  new allocs/op  delta
DetailString-8      63.0 ± 0%      50.0 ± 0%  -20.63%  (p=0.000 n=20+20)

Change-Id: I47a2827cd34d6b92644900b1bd5f4c0a3287bdb1
Reviewed-on: https://go-review.googlesource.com/c/go/+/429861
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-by: hopehook <hopehook@golangcn.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
This commit is contained in:
Emmanuel T Odeke 2022-09-09 09:59:21 -07:00 committed by Emmanuel Odeke
parent a7e9a379e9
commit 4baa486983
8 changed files with 14 additions and 14 deletions

View File

@ -339,7 +339,7 @@ func (t *T) String() string {
}
b.WriteString(strconv.FormatInt(int64(k), 10))
b.WriteString(":")
b.WriteString(fmt.Sprint(v))
fmt.Fprint(&b, v)
}
return b.String()
}

View File

@ -7271,7 +7271,7 @@ func genssa(f *ssa.Func, pp *objw.Progs) {
}
buf.WriteString("</dt>")
buf.WriteString("<dd class=\"ssa-prog\">")
buf.WriteString(fmt.Sprintf("%.5d <span class=\"l%v line-number\">(%s)</span> %s", p.Pc, p.InnermostLineNumber(), p.InnermostLineNumberHTML(), html.EscapeString(p.InstructionString())))
fmt.Fprintf(&buf, "%.5d <span class=\"l%v line-number\">(%s)</span> %s", p.Pc, p.InnermostLineNumber(), p.InnermostLineNumberHTML(), html.EscapeString(p.InstructionString()))
buf.WriteString("</dd>")
}
buf.WriteString("</dl>")

View File

@ -88,10 +88,10 @@ func TestEmbeddedTokens(t *testing.T) {
// make source
var buf bytes.Buffer
for i, s := range sampleTokens {
buf.WriteString("\t\t\t\t"[:i&3]) // leading indentation
buf.WriteString(s.src) // token
buf.WriteString(" "[:i&7]) // trailing spaces
buf.WriteString(fmt.Sprintf("/*line foo:%d */ // bar\n", i)) // comments + newline (don't crash w/o directive handler)
buf.WriteString("\t\t\t\t"[:i&3]) // leading indentation
buf.WriteString(s.src) // token
buf.WriteString(" "[:i&7]) // trailing spaces
fmt.Fprintf(&buf, "/*line foo:%d */ // bar\n", i) // comments + newline (don't crash w/o directive handler)
}
// scan source

View File

@ -577,7 +577,7 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type
} else {
b.WriteString("tp")
// Print out the pointer value for now to disambiguate type params
b.WriteString(fmt.Sprintf("%p", t))
fmt.Fprintf(b, "%p", t)
}
case TUNION:

View File

@ -33,7 +33,7 @@ func WriteExpr(buf *bytes.Buffer, x ast.Expr) {
switch x := x.(type) {
default:
buf.WriteString(fmt.Sprintf("(ast: %T)", x)) // nil, ast.BadExpr, ast.KeyValueExpr
fmt.Fprintf(buf, "(ast: %T)", x) // nil, ast.BadExpr, ast.KeyValueExpr
case *ast.Ident:
buf.WriteString(x.Name)

View File

@ -147,7 +147,7 @@ func sprint(data any) string {
}
b.WriteString(sprintKey(key))
b.WriteRune(':')
b.WriteString(fmt.Sprint(om.Value[i]))
fmt.Fprint(b, om.Value[i])
}
return b.String()
}

View File

@ -147,7 +147,7 @@ func TestUserTaskRegion(t *testing.T) {
pretty := func(data []testData) string {
var s strings.Builder
for _, d := range data {
s.WriteString(fmt.Sprintf("\t%+v\n", d))
fmt.Fprintf(&s, "\t%+v\n", d)
}
return s.String()
}

View File

@ -62,7 +62,7 @@ func genasmArm() {
TEXT runtime·callbackasm(SB),NOSPLIT|NOFRAME,$0
`)
for i := 0; i < maxCallback; i++ {
buf.WriteString(fmt.Sprintf("\tMOVW\t$%d, R12\n", i))
fmt.Fprintf(&buf, "\tMOVW\t$%d, R12\n", i)
buf.WriteString("\tB\truntime·callbackasm1(SB)\n")
}
@ -90,7 +90,7 @@ func genasmArm64() {
TEXT runtime·callbackasm(SB),NOSPLIT|NOFRAME,$0
`)
for i := 0; i < maxCallback; i++ {
buf.WriteString(fmt.Sprintf("\tMOVD\t$%d, R12\n", i))
fmt.Fprintf(&buf, "\tMOVD\t$%d, R12\n", i)
buf.WriteString("\tB\truntime·callbackasm1(SB)\n")
}
@ -104,12 +104,12 @@ TEXT runtime·callbackasm(SB),NOSPLIT|NOFRAME,$0
func gengo() {
var buf bytes.Buffer
buf.WriteString(fmt.Sprintf(`// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
fmt.Fprintf(&buf, `// Code generated by wincallback.go using 'go generate'. DO NOT EDIT.
package runtime
const cb_max = %d // maximum number of windows callbacks allowed
`, maxCallback))
`, maxCallback)
err := os.WriteFile("zcallback_windows.go", buf.Bytes(), 0666)
if err != nil {
fmt.Fprintf(os.Stderr, "wincallback: %s\n", err)