Futher reduce allocations across hot paths
This commit is contained in:
parent
6b90b94e07
commit
17ad74b4fc
|
@ -1,7 +0,0 @@
|
||||||
goos: darwin
|
|
||||||
goarch: amd64
|
|
||||||
pkg: github.com/dosco/super-graph/psql
|
|
||||||
BenchmarkCompile-8 50000 27388 ns/op 4983 B/op 136 allocs/op
|
|
||||||
BenchmarkCompileParallel-8 200000 8864 ns/op 5046 B/op 136 allocs/op
|
|
||||||
PASS
|
|
||||||
ok github.com/dosco/super-graph/psql 3.528s
|
|
|
@ -1,7 +0,0 @@
|
||||||
goos: darwin
|
|
||||||
goarch: amd64
|
|
||||||
pkg: github.com/dosco/super-graph/psql
|
|
||||||
BenchmarkCompile-8 50000 26899 ns/op 4984 B/op 136 allocs/op
|
|
||||||
BenchmarkCompileParallel-8 200000 8128 ns/op 5046 B/op 136 allocs/op
|
|
||||||
PASS
|
|
||||||
ok github.com/dosco/super-graph/psql 3.455s
|
|
|
@ -1,7 +0,0 @@
|
||||||
goos: darwin
|
|
||||||
goarch: amd64
|
|
||||||
pkg: github.com/dosco/super-graph/psql
|
|
||||||
BenchmarkCompile-8 50000 25670 ns/op 4533 B/op 134 allocs/op
|
|
||||||
BenchmarkCompileParallel-8 200000 7533 ns/op 4590 B/op 134 allocs/op
|
|
||||||
PASS
|
|
||||||
ok github.com/dosco/super-graph/psql 3.149s
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
goos: darwin
|
||||||
|
goarch: amd64
|
||||||
|
pkg: github.com/dosco/super-graph/psql
|
||||||
|
BenchmarkCompile-8 1000000 15997 ns/op 3048 B/op 58 allocs/op
|
||||||
|
BenchmarkCompileParallel-8 3000000 4722 ns/op 3073 B/op 58 allocs/op
|
||||||
|
PASS
|
||||||
|
ok github.com/dosco/super-graph/psql 35.024s
|
|
@ -0,0 +1,7 @@
|
||||||
|
goos: darwin
|
||||||
|
goarch: amd64
|
||||||
|
pkg: github.com/dosco/super-graph/psql
|
||||||
|
BenchmarkCompile-8 100000 16829 ns/op 2887 B/op 57 allocs/op
|
||||||
|
BenchmarkCompileParallel-8 300000 5450 ns/op 2911 B/op 57 allocs/op
|
||||||
|
PASS
|
||||||
|
ok github.com/dosco/super-graph/psql 3.561s
|
|
@ -0,0 +1,7 @@
|
||||||
|
goos: darwin
|
||||||
|
goarch: amd64
|
||||||
|
pkg: github.com/dosco/super-graph/psql
|
||||||
|
BenchmarkCompile-8 100000 15246 ns/op 2823 B/op 53 allocs/op
|
||||||
|
BenchmarkCompileParallel-8 300000 4559 ns/op 2848 B/op 53 allocs/op
|
||||||
|
PASS
|
||||||
|
ok github.com/dosco/super-graph/psql 3.116s
|
|
@ -70,6 +70,7 @@ type Node struct {
|
||||||
Val string
|
Val string
|
||||||
Parent *Node
|
Parent *Node
|
||||||
Children []*Node
|
Children []*Node
|
||||||
|
exp *Exp
|
||||||
}
|
}
|
||||||
|
|
||||||
var zeroNode = Node{}
|
var zeroNode = Node{}
|
||||||
|
@ -217,10 +218,8 @@ func (p *Parser) peek(types ...itemType) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) parseOp() (*Operation, error) {
|
func (p *Parser) parseOp() (*Operation, error) {
|
||||||
if p.peek(itemQuery, itemMutation, itemSub) == false {
|
if !p.peek(itemQuery, itemMutation, itemSub) {
|
||||||
err := fmt.Errorf(
|
err := errors.New("expecting a query, mutation or subscription")
|
||||||
"expecting a query, mutation or subscription (not '%s')",
|
|
||||||
p.val(p.next()))
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
item := p.next()
|
item := p.next()
|
||||||
|
|
|
@ -179,6 +179,11 @@ func NewCompiler(c Config) (*Compiler, error) {
|
||||||
fm[plural] = fil
|
fm[plural] = fil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
seedExp := [100]Exp{}
|
||||||
|
for i := range seedExp {
|
||||||
|
expPool.Put(&seedExp[i])
|
||||||
|
}
|
||||||
|
|
||||||
return &Compiler{fl, fm, bl, c.KeepArgs}, nil
|
return &Compiler{fl, fm, bl, c.KeepArgs}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +238,7 @@ func (com *Compiler) compileQuery(op *Operation) (*Query, error) {
|
||||||
parentID := int32(0)
|
parentID := int32(0)
|
||||||
|
|
||||||
selects := make([]Select, 0, 5)
|
selects := make([]Select, 0, 5)
|
||||||
st := util.NewStack()
|
st := NewStack()
|
||||||
|
|
||||||
if len(op.Fields) == 0 {
|
if len(op.Fields) == 0 {
|
||||||
return nil, errors.New("empty query")
|
return nil, errors.New("empty query")
|
||||||
|
@ -249,12 +254,7 @@ func (com *Compiler) compileQuery(op *Operation) (*Query, error) {
|
||||||
return nil, fmt.Errorf("selector limit reached (%d)", maxSelectors)
|
return nil, fmt.Errorf("selector limit reached (%d)", maxSelectors)
|
||||||
}
|
}
|
||||||
|
|
||||||
intf := st.Pop()
|
fid := st.Pop()
|
||||||
fid, ok := intf.(int32)
|
|
||||||
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("15: unexpected value %v (%t)", intf, intf)
|
|
||||||
}
|
|
||||||
field := &op.Fields[fid]
|
field := &op.Fields[fid]
|
||||||
|
|
||||||
if _, ok := com.bl[field.Name]; ok {
|
if _, ok := com.bl[field.Name]; ok {
|
||||||
|
@ -328,7 +328,10 @@ func (com *Compiler) compileQuery(op *Operation) (*Query, error) {
|
||||||
|
|
||||||
if root.Where != nil {
|
if root.Where != nil {
|
||||||
ow := root.Where
|
ow := root.Where
|
||||||
root.Where = &Exp{Op: OpAnd}
|
|
||||||
|
root.Where = expPool.Get().(*Exp)
|
||||||
|
root.Where.Reset()
|
||||||
|
root.Where.Op = OpAnd
|
||||||
root.Where.Children = root.Where.childrenA[:2]
|
root.Where.Children = root.Where.childrenA[:2]
|
||||||
root.Where.Children[0] = fil
|
root.Where.Children[0] = fil
|
||||||
root.Where.Children[1] = ow
|
root.Where.Children[1] = ow
|
||||||
|
@ -387,11 +390,6 @@ func (com *Compiler) compileArgs(sel *Select, args []Arg) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type expT struct {
|
|
||||||
parent *Exp
|
|
||||||
node *Node
|
|
||||||
}
|
|
||||||
|
|
||||||
func (com *Compiler) compileArgObj(arg *Arg) (*Exp, error) {
|
func (com *Compiler) compileArgObj(arg *Arg) (*Exp, error) {
|
||||||
if arg.Val.Type != nodeObj {
|
if arg.Val.Type != nodeObj {
|
||||||
return nil, fmt.Errorf("expecting an object")
|
return nil, fmt.Errorf("expecting an object")
|
||||||
|
@ -408,7 +406,7 @@ func (com *Compiler) compileArgNode(node *Node, usePool bool) (*Exp, error) {
|
||||||
return nil, errors.New("invalid argument value")
|
return nil, errors.New("invalid argument value")
|
||||||
}
|
}
|
||||||
|
|
||||||
st.Push(&expT{nil, node.Children[0]})
|
pushChild(st, nil, node)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if st.Len() == 0 {
|
if st.Len() == 0 {
|
||||||
|
@ -416,18 +414,22 @@ func (com *Compiler) compileArgNode(node *Node, usePool bool) (*Exp, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
intf := st.Pop()
|
intf := st.Pop()
|
||||||
eT, ok := intf.(*expT)
|
node, ok := intf.(*Node)
|
||||||
if !ok || eT == nil {
|
if !ok || node == nil {
|
||||||
return nil, fmt.Errorf("16: unexpected value %v (%t)", intf, intf)
|
return nil, fmt.Errorf("16: unexpected value %v (%t)", intf, intf)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(eT.node.Name) != 0 {
|
if len(node.Name) == 0 {
|
||||||
if _, ok := com.bl[eT.node.Name]; ok {
|
pushChildren(st, node.exp, node)
|
||||||
|
continue
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if _, ok := com.bl[node.Name]; ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ex, err := newExp(st, eT, usePool)
|
ex, err := newExp(st, node, usePool)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -436,18 +438,19 @@ func (com *Compiler) compileArgNode(node *Node, usePool bool) (*Exp, error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if eT.parent == nil {
|
if node.exp == nil {
|
||||||
root = ex
|
root = ex
|
||||||
} else {
|
} else {
|
||||||
eT.parent.Children = append(eT.parent.Children, ex)
|
node.exp.Children = append(node.exp.Children, ex)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if com.ka {
|
if com.ka {
|
||||||
return root, nil
|
return root, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
st.Push(node.Children[0])
|
pushChild(st, nil, node)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if st.Len() == 0 {
|
if st.Len() == 0 {
|
||||||
|
@ -503,7 +506,10 @@ func (com *Compiler) compileArgSearch(sel *Select, arg *Arg) error {
|
||||||
|
|
||||||
if sel.Where != nil {
|
if sel.Where != nil {
|
||||||
ow := sel.Where
|
ow := sel.Where
|
||||||
sel.Where = &Exp{Op: OpAnd}
|
|
||||||
|
sel.Where = expPool.Get().(*Exp)
|
||||||
|
sel.Where.Reset()
|
||||||
|
sel.Where.Op = OpAnd
|
||||||
sel.Where.Children = sel.Where.childrenA[:2]
|
sel.Where.Children = sel.Where.childrenA[:2]
|
||||||
sel.Where.Children[0] = ex
|
sel.Where.Children[0] = ex
|
||||||
sel.Where.Children[1] = ow
|
sel.Where.Children[1] = ow
|
||||||
|
@ -523,7 +529,10 @@ func (com *Compiler) compileArgWhere(sel *Select, arg *Arg) error {
|
||||||
|
|
||||||
if sel.Where != nil {
|
if sel.Where != nil {
|
||||||
ow := sel.Where
|
ow := sel.Where
|
||||||
sel.Where = &Exp{Op: OpAnd}
|
|
||||||
|
sel.Where = expPool.Get().(*Exp)
|
||||||
|
sel.Where.Reset()
|
||||||
|
sel.Where.Op = OpAnd
|
||||||
sel.Where.Children = sel.Where.childrenA[:2]
|
sel.Where.Children = sel.Where.childrenA[:2]
|
||||||
sel.Where.Children[0] = ex
|
sel.Where.Children[0] = ex
|
||||||
sel.Where.Children[1] = ow
|
sel.Where.Children[1] = ow
|
||||||
|
@ -659,14 +668,7 @@ func compileSub() (*Query, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newExp(st *util.Stack, eT *expT, usePool bool) (*Exp, error) {
|
func newExp(st *util.Stack, node *Node, usePool bool) (*Exp, error) {
|
||||||
node := eT.node
|
|
||||||
|
|
||||||
if len(node.Name) == 0 {
|
|
||||||
pushChildren(st, eT.parent, node)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
name := node.Name
|
name := node.Name
|
||||||
if name[0] == '_' {
|
if name[0] == '_' {
|
||||||
name = name[1:]
|
name = name[1:]
|
||||||
|
@ -691,7 +693,7 @@ func newExp(st *util.Stack, eT *expT, usePool bool) (*Exp, error) {
|
||||||
pushChildren(st, ex, node)
|
pushChildren(st, ex, node)
|
||||||
case "not":
|
case "not":
|
||||||
ex.Op = OpNot
|
ex.Op = OpNot
|
||||||
st.Push(&expT{ex, node.Children[0]})
|
pushChild(st, ex, node)
|
||||||
case "eq", "equals":
|
case "eq", "equals":
|
||||||
ex.Op = OpEquals
|
ex.Op = OpEquals
|
||||||
ex.Val = node.Val
|
ex.Val = node.Val
|
||||||
|
@ -753,7 +755,7 @@ func newExp(st *util.Stack, eT *expT, usePool bool) (*Exp, error) {
|
||||||
ex.Op = OpIsNull
|
ex.Op = OpIsNull
|
||||||
ex.Val = node.Val
|
ex.Val = node.Val
|
||||||
default:
|
default:
|
||||||
pushChildren(st, eT.parent, node)
|
pushChildren(st, node.exp, node)
|
||||||
return nil, nil // skip node
|
return nil, nil // skip node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -836,12 +838,18 @@ func setOrderByColName(ob *OrderBy, node *Node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func pushChildren(st *util.Stack, ex *Exp, node *Node) {
|
func pushChildren(st *util.Stack, exp *Exp, node *Node) {
|
||||||
for i := range node.Children {
|
for i := range node.Children {
|
||||||
st.Push(&expT{ex, node.Children[i]})
|
node.Children[i].exp = exp
|
||||||
|
st.Push(node.Children[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pushChild(st *util.Stack, exp *Exp, node *Node) {
|
||||||
|
node.Children[0].exp = exp
|
||||||
|
st.Push(node.Children[0])
|
||||||
|
}
|
||||||
|
|
||||||
func compileFilter(filter []string) (*Exp, error) {
|
func compileFilter(filter []string) (*Exp, error) {
|
||||||
var fl *Exp
|
var fl *Exp
|
||||||
com := &Compiler{}
|
com := &Compiler{}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package qcode
|
||||||
|
|
||||||
|
type Stack struct {
|
||||||
|
stA [20]int32
|
||||||
|
st []int32
|
||||||
|
top int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new Stack
|
||||||
|
func NewStack() *Stack {
|
||||||
|
s := &Stack{top: -1}
|
||||||
|
s.st = s.stA[:0]
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the number of items in the Stack
|
||||||
|
func (s *Stack) Len() int {
|
||||||
|
return (s.top + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// View the top item on the Stack
|
||||||
|
func (s *Stack) Peek() int32 {
|
||||||
|
if s.top == -1 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return s.st[s.top]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pop the top item of the Stack and return it
|
||||||
|
func (s *Stack) Pop() int32 {
|
||||||
|
if s.top == -1 {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
s.top--
|
||||||
|
return s.st[(s.top + 1)]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push a value onto the top of the Stack
|
||||||
|
func (s *Stack) Push(value int32) {
|
||||||
|
s.top++
|
||||||
|
if len(s.st) <= s.top {
|
||||||
|
s.st = append(s.st, value)
|
||||||
|
} else {
|
||||||
|
s.st[s.top] = value
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue