diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-12-08 12:27:39 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-12-08 12:27:39 +0100 |
| commit | b0fa969c096608d3411359b3d0c4f95b95ddc2d5 (patch) | |
| tree | 12f81affe7956b7e6039346e06cbedd06ff80eb6 /prog/clone.go | |
| parent | 5e7b20cfc3d38b457f3282bf8227737a8ee4eecd (diff) | |
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%
Diffstat (limited to 'prog/clone.go')
| -rw-r--r-- | prog/clone.go | 33 |
1 files changed, 14 insertions, 19 deletions
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 } |
