From 86cd6c2ee5c5e4c5b5edf4ea8d1c85f80d9706a8 Mon Sep 17 00:00:00 2001 From: Ariel Mashraki Date: Tue, 1 Oct 2019 18:39:29 +0300 Subject: [PATCH] text/template/parse: use strings.Builder in Chain and List nodes This CL is a continuation of 198078. Benchmark output: benchmark old ns/op new ns/op delta BenchmarkParseLarge-8 24759165 24516563 -0.98% BenchmarkVariableString-8 115 115 +0.00% BenchmarkListString-8 924 680 -26.41% benchmark old allocs new allocs delta BenchmarkVariableString-8 3 3 +0.00% BenchmarkListString-8 14 13 -7.14% benchmark old bytes new bytes delta BenchmarkVariableString-8 72 72 +0.00% BenchmarkListString-8 512 424 -17.19% Change-Id: I9ec48fe4832437c556a5fa94d4cbf6e29e28d944 Reviewed-on: https://go-review.googlesource.com/c/go/+/198080 Reviewed-by: Emmanuel Odeke Run-TryBot: Emmanuel Odeke TryBot-Result: Gobot Gobot --- src/text/template/parse/node.go | 20 ++++++++++++-------- src/text/template/parse/parse_test.go | 22 +++++++++++++++++++--- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/text/template/parse/node.go b/src/text/template/parse/node.go index 2eb1af0a95..61c6853679 100644 --- a/src/text/template/parse/node.go +++ b/src/text/template/parse/node.go @@ -7,7 +7,6 @@ package parse import ( - "bytes" "fmt" "strconv" "strings" @@ -94,11 +93,11 @@ func (l *ListNode) tree() *Tree { } func (l *ListNode) String() string { - b := new(bytes.Buffer) + var sb strings.Builder for _, n := range l.Nodes { - fmt.Fprint(b, n) + sb.WriteString(n.String()) } - return b.String() + return sb.String() } func (l *ListNode) CopyList() *ListNode { @@ -472,14 +471,19 @@ func (c *ChainNode) Add(field string) { } func (c *ChainNode) String() string { - s := c.Node.String() + var sb strings.Builder if _, ok := c.Node.(*PipeNode); ok { - s = "(" + s + ")" + sb.WriteByte('(') + sb.WriteString(c.Node.String()) + sb.WriteByte(')') + } else { + sb.WriteString(c.Node.String()) } for _, field := range c.Field { - s += "." + field + sb.WriteByte('.') + sb.WriteString(field) } - return s + return sb.String() } func (c *ChainNode) tree() *Tree { diff --git a/src/text/template/parse/parse_test.go b/src/text/template/parse/parse_test.go index 371de5d67c..86a100bb5f 100644 --- a/src/text/template/parse/parse_test.go +++ b/src/text/template/parse/parse_test.go @@ -554,7 +554,7 @@ func BenchmarkParseLarge(b *testing.B) { } } -var sink string +var sinkv, sinkl string func BenchmarkVariableString(b *testing.B) { v := &VariableNode{ @@ -563,9 +563,25 @@ func BenchmarkVariableString(b *testing.B) { b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { - sink = v.String() + sinkv = v.String() } - if sink == "" { + if sinkv == "" { + b.Fatal("Benchmark was not run") + } +} + +func BenchmarkListString(b *testing.B) { + text := `{{ (printf .Field1.Field2.Field3).Value }}` + tree, err := New("bench").Parse(text, "", "", make(map[string]*Tree), builtins) + if err != nil { + b.Fatal(err) + } + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + sinkl = tree.Root.String() + } + if sinkl == "" { b.Fatal("Benchmark was not run") } } -- 2.50.0