]> Cypherpunks repositories - gostls13.git/commitdiff
text/template/parse: use strings.Builder in String methods
authorAriel Mashraki <ariel@mashraki.co.il>
Mon, 30 Sep 2019 22:10:44 +0000 (01:10 +0300)
committerEmmanuel Odeke <emm.odeke@gmail.com>
Tue, 1 Oct 2019 07:16:47 +0000 (07:16 +0000)
As mentioned in godoc, strings.Builder is more efficient for
concatenating and building strings.
Running a simple bench test on VariableNode.String() gives:

benchmark                     old ns/op     new ns/op     delta
BenchmarkParseLarge-8         25676831      24453285      -4.77%
BenchmarkVariableString-8     296           115           -61.15%

benchmark                     old allocs     new allocs     delta
BenchmarkVariableString-8     8              3              -62.50%

benchmark                     old bytes     new bytes     delta
BenchmarkVariableString-8     112           72            -35.71%

Change-Id: I13c9340080738fcad1edeed859d33ba608e4b05a
Reviewed-on: https://go-review.googlesource.com/c/go/+/198078
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/text/template/parse/node.go
src/text/template/parse/parse_test.go

index 2f921be2ecf92ee4f2a5aa23fbb70b68e8e43eed..2eb1af0a952a741c9eb9151064b53b44c772c376 100644 (file)
@@ -160,23 +160,23 @@ func (p *PipeNode) append(command *CommandNode) {
 }
 
 func (p *PipeNode) String() string {
-       s := ""
+       var sb strings.Builder
        if len(p.Decl) > 0 {
                for i, v := range p.Decl {
                        if i > 0 {
-                               s += ", "
+                               sb.WriteString(", ")
                        }
-                       s += v.String()
+                       sb.WriteString(v.String())
                }
-               s += " := "
+               sb.WriteString(" := ")
        }
        for i, c := range p.Cmds {
                if i > 0 {
-                       s += " | "
+                       sb.WriteString(" | ")
                }
-               s += c.String()
+               sb.WriteString(c.String())
        }
-       return s
+       return sb.String()
 }
 
 func (p *PipeNode) tree() *Tree {
@@ -249,18 +249,20 @@ func (c *CommandNode) append(arg Node) {
 }
 
 func (c *CommandNode) String() string {
-       s := ""
+       var sb strings.Builder
        for i, arg := range c.Args {
                if i > 0 {
-                       s += " "
+                       sb.WriteByte(' ')
                }
                if arg, ok := arg.(*PipeNode); ok {
-                       s += "(" + arg.String() + ")"
+                       sb.WriteByte('(')
+                       sb.WriteString(arg.String())
+                       sb.WriteByte(')')
                        continue
                }
-               s += arg.String()
+               sb.WriteString(arg.String())
        }
-       return s
+       return sb.String()
 }
 
 func (c *CommandNode) tree() *Tree {
@@ -333,14 +335,14 @@ func (t *Tree) newVariable(pos Pos, ident string) *VariableNode {
 }
 
 func (v *VariableNode) String() string {
-       s := ""
+       var sb strings.Builder
        for i, id := range v.Ident {
                if i > 0 {
-                       s += "."
+                       sb.WriteByte('.')
                }
-               s += id
+               sb.WriteString(id)
        }
-       return s
+       return sb.String()
 }
 
 func (v *VariableNode) tree() *Tree {
@@ -426,11 +428,12 @@ func (t *Tree) newField(pos Pos, ident string) *FieldNode {
 }
 
 func (f *FieldNode) String() string {
-       s := ""
+       var sb strings.Builder
        for _, id := range f.Ident {
-               s += "." + id
+               sb.WriteByte('.')
+               sb.WriteString(id)
        }
-       return s
+       return sb.String()
 }
 
 func (f *FieldNode) tree() *Tree {
index 6932cf232ea4a4e5f7a7d41def31a263786b96bc..371de5d67ccd5a9204a6ebae2e8a966c6560f35d 100644 (file)
@@ -553,3 +553,19 @@ func BenchmarkParseLarge(b *testing.B) {
                }
        }
 }
+
+var sink string
+
+func BenchmarkVariableString(b *testing.B) {
+       v := &VariableNode{
+               Ident: []string{"$", "A", "BB", "CCC", "THIS_IS_THE_VARIABLE_BEING_PROCESSED"},
+       }
+       b.ResetTimer()
+       b.ReportAllocs()
+       for i := 0; i < b.N; i++ {
+               sink = v.String()
+       }
+       if sink == "" {
+               b.Fatal("Benchmark was not run")
+       }
+}