diff --git a/builder/evaluator.go b/builder/evaluator.go index 645038bb1d..3f2600e29d 100644 --- a/builder/evaluator.go +++ b/builder/evaluator.go @@ -211,6 +211,21 @@ func (b *Builder) dispatch(stepN int, ast *parser.Node) error { msg += " " + ast.Value } + // count the number of nodes that we are going to traverse first + // so we can pre-create the argument and message array. This speeds up the + // allocation of those list a lot when they have a lot of arguments + cursor := ast + var n int + for cursor.Next != nil { + cursor = cursor.Next + n++ + } + l := len(strs) + strList := make([]string, n+l) + copy(strList, strs) + msgList := make([]string, n) + + var i int for ast.Next != nil { ast = ast.Next var str string @@ -218,16 +233,18 @@ func (b *Builder) dispatch(stepN int, ast *parser.Node) error { if _, ok := replaceEnvAllowed[cmd]; ok { str = b.replaceEnv(ast.Value) } - strs = append(strs, str) - msg += " " + ast.Value + strList[i+l] = str + msgList[i] = ast.Value + i++ } + msg += " " + strings.Join(msgList, " ") fmt.Fprintln(b.OutStream, msg) // XXX yes, we skip any cmds that are not valid; the parser should have // picked these out already. if f, ok := evaluateTable[cmd]; ok { - return f(b, strs, attrs, original) + return f(b, strList, attrs, original) } fmt.Fprintf(b.ErrStream, "# Skipping unknown instruction %s\n", strings.ToUpper(cmd))