diff --git a/psql/bench.5 b/psql/bench.5 new file mode 100644 index 0000000..9e9eaf1 --- /dev/null +++ b/psql/bench.5 @@ -0,0 +1,7 @@ +goos: darwin +goarch: amd64 +pkg: github.com/dosco/super-graph/psql +BenchmarkCompile-8 100000 15728 ns/op 3000 B/op 60 allocs/op +BenchmarkCompileParallel-8 300000 5077 ns/op 3023 B/op 60 allocs/op +PASS +ok github.com/dosco/super-graph/psql 3.318s diff --git a/psql/psql.go b/psql/psql.go index e277d42..00213c0 100644 --- a/psql/psql.go +++ b/psql/psql.go @@ -657,10 +657,12 @@ func (c *compilerContext) renderWhere(sel *qcode.Select, ti *DBTableInfo) error st.Push(val.Op) } } + qcode.FreeExp(val) continue case qcode.OpNot: st.Push(val.Children[0]) st.Push(qcode.OpNot) + qcode.FreeExp(val) continue } @@ -669,6 +671,7 @@ func (c *compilerContext) renderWhere(sel *qcode.Select, ti *DBTableInfo) error c.w.WriteString(`(("`) c.w.WriteString(val.Col) c.w.WriteString(`") `) + } else if len(val.Col) != 0 { //fmt.Fprintf(w, `(("%s"."%s") `, c.sel.Table, val.Col) c.w.WriteString(`((`) @@ -757,9 +760,12 @@ func (c *compilerContext) renderWhere(sel *qcode.Select, ti *DBTableInfo) error c.w.WriteString(`)`) } + qcode.FreeExp(val) + default: return fmt.Errorf("12: unexpected value %v (%t)", intf, intf) } + } return nil diff --git a/qcode/parse.go b/qcode/parse.go index 578cb7b..b1f42d5 100644 --- a/qcode/parse.go +++ b/qcode/parse.go @@ -523,6 +523,6 @@ func (t parserType) String() string { return fmt.Sprintf("<%s>", v) } -func PutNode(n *Node) { +func FreeNode(n *Node) { nodePool.Put(n) } diff --git a/qcode/qcode.go b/qcode/qcode.go index 3c098db..0d583be 100644 --- a/qcode/qcode.go +++ b/qcode/qcode.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "strings" + "sync" "github.com/dosco/super-graph/util" "github.com/gobuffalo/flect" @@ -51,6 +52,13 @@ type Exp struct { ListVal []string Children []*Exp childrenA [5]*Exp + doFree bool +} + +var zeroExp = Exp{doFree: true} + +func (ex *Exp) Reset() { + *ex = zeroExp } type OrderBy struct { @@ -141,6 +149,10 @@ type Compiler struct { ka bool } +var expPool = sync.Pool{ + New: func() interface{} { return new(Exp) }, +} + func NewCompiler(c Config) (*Compiler, error) { bl := make(map[string]struct{}, len(c.Blacklist)) @@ -385,10 +397,10 @@ func (com *Compiler) compileArgObj(arg *Arg) (*Exp, error) { return nil, fmt.Errorf("expecting an object") } - return com.compileArgNode(arg.Val) + return com.compileArgNode(arg.Val, true) } -func (com *Compiler) compileArgNode(node *Node) (*Exp, error) { +func (com *Compiler) compileArgNode(node *Node, usePool bool) (*Exp, error) { st := util.NewStack() var root *Exp @@ -415,8 +427,7 @@ func (com *Compiler) compileArgNode(node *Node) (*Exp, error) { } } - ex, err := newExp(st, eT) - + ex, err := newExp(st, eT, usePool) if err != nil { return nil, err } @@ -459,7 +470,11 @@ func (com *Compiler) compileArgID(sel *Select, arg *Arg) error { return nil } - ex := &Exp{Op: OpEqID, Val: arg.Val.Val} + ex := expPool.Get().(*Exp) + ex.Reset() + + ex.Op = OpEqID + ex.Val = arg.Val.Val switch arg.Val.Type { case nodeStr: @@ -479,11 +494,12 @@ func (com *Compiler) compileArgID(sel *Select, arg *Arg) error { } func (com *Compiler) compileArgSearch(sel *Select, arg *Arg) error { - ex := &Exp{ - Op: OpTsQuery, - Type: ValStr, - Val: arg.Val.Val, - } + ex := expPool.Get().(*Exp) + ex.Reset() + + ex.Op = OpTsQuery + ex.Type = ValStr + ex.Val = arg.Val.Val if sel.Where != nil { ow := sel.Where @@ -643,7 +659,7 @@ func compileSub() (*Query, error) { return nil, nil } -func newExp(st *util.Stack, eT *expT) (*Exp, error) { +func newExp(st *util.Stack, eT *expT, usePool bool) (*Exp, error) { node := eT.node if len(node.Name) == 0 { @@ -656,7 +672,15 @@ func newExp(st *util.Stack, eT *expT) (*Exp, error) { name = name[1:] } - ex := &Exp{} + var ex *Exp + + if usePool { + ex = expPool.Get().(*Exp) + ex.Reset() + } else { + ex = &Exp{} + } + ex.Children = ex.childrenA[:0] switch name { case "and": @@ -831,7 +855,7 @@ func compileFilter(filter []string) (*Exp, error) { if err != nil { return nil, err } - f, err := com.compileArgNode(node) + f, err := com.compileArgNode(node, false) if err != nil { return nil, err } @@ -926,3 +950,9 @@ func (t ExpOp) String() string { } return fmt.Sprintf("<%s>", v) } + +func FreeExp(ex *Exp) { + if ex.doFree { + expPool.Put(ex) + } +}