From b0fa969c096608d3411359b3d0c4f95b95ddc2d5 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Fri, 8 Dec 2017 12:27:39 +0100 Subject: prog: speedup and simplify hints code Clone program only once. Preallocate slices in clone. Remove the clone full mode. Always mutate args in place. Allocate replacers map lazily. Don't allocate res map at all (calculate valus on the go). Remove sliceToUint64, pad. benchmark old ns/op new ns/op delta BenchmarkHints 122100048 7466013 -93.89% --- prog/clone.go | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) (limited to 'prog/clone.go') diff --git a/prog/clone.go b/prog/clone.go index 2253c7e75..1ff42f60f 100644 --- a/prog/clone.go +++ b/prog/clone.go @@ -4,33 +4,30 @@ package prog func (p *Prog) Clone() *Prog { - p1, _ := p.cloneImpl(false) - return p1 -} - -func (p *Prog) cloneImpl(full bool) (*Prog, map[Arg]Arg) { p1 := &Prog{ Target: p.Target, + Calls: make([]*Call, len(p.Calls)), } newargs := make(map[Arg]Arg) - for _, c := range p.Calls { + for ci, c := range p.Calls { c1 := new(Call) c1.Meta = c.Meta - c1.Ret = clone(c.Ret, newargs, full) - for _, arg := range c.Args { - c1.Args = append(c1.Args, clone(arg, newargs, full)) + c1.Ret = clone(c.Ret, newargs) + c1.Args = make([]Arg, len(c.Args)) + for ai, arg := range c.Args { + c1.Args[ai] = clone(arg, newargs) } - p1.Calls = append(p1.Calls, c1) + p1.Calls[ci] = c1 } if debug { if err := p1.validate(); err != nil { panic(err) } } - return p1, newargs + return p1 } -func clone(arg Arg, newargs map[Arg]Arg, full bool) Arg { +func clone(arg Arg, newargs map[Arg]Arg) Arg { var arg1 Arg switch a := arg.(type) { case *ConstArg: @@ -42,7 +39,7 @@ func clone(arg Arg, newargs map[Arg]Arg, full bool) Arg { *a1 = *a arg1 = a1 if a.Res != nil { - a1.Res = clone(a.Res, newargs, full) + a1.Res = clone(a.Res, newargs) } case *DataArg: a1 := new(DataArg) @@ -53,15 +50,15 @@ func clone(arg Arg, newargs map[Arg]Arg, full bool) Arg { a1 := new(GroupArg) *a1 = *a arg1 = a1 - a1.Inner = nil - for _, arg2 := range a.Inner { - a1.Inner = append(a1.Inner, clone(arg2, newargs, full)) + a1.Inner = make([]Arg, len(a.Inner)) + for i, arg2 := range a.Inner { + a1.Inner[i] = clone(arg2, newargs) } case *UnionArg: a1 := new(UnionArg) *a1 = *a arg1 = a1 - a1.Option = clone(a.Option, newargs, full) + a1.Option = clone(a.Option, newargs) case *ResultArg: a1 := new(ResultArg) *a1 = *a @@ -85,8 +82,6 @@ func clone(arg Arg, newargs map[Arg]Arg, full bool) Arg { if used, ok := arg1.(ArgUsed); ok { *used.Used() = nil // filled when we clone the referent newargs[arg] = arg1 - } else if full { - newargs[arg] = arg1 } return arg1 } -- cgit mrf-deployment