Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Faster printer.Print #682

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 24 additions & 0 deletions language/printer/printer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,27 @@ func TestPrinter_CorrectlyPrintsStringArgumentsWithProperQuoting(t *testing.T) {
t.Fatalf("Unexpected result, Diff: %v", testutil.Diff(expected, results))
}
}

func BenchmarkPrint(b *testing.B) {
q, err := ioutil.ReadFile("../../kitchen-sink.graphql")
if err != nil {
b.Fatalf("unable to load kitchen-sink.graphql")
}

query := string(q)

astDoc, err := parser.Parse(parser.ParseParams{
Source: query,
Options: parser.ParseOptions{
NoLocation: true,
},
})
if err != nil {
b.Fatalf("Parse failed: %v", err)
}

b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = printer.Print(astDoc)
}
}
64 changes: 56 additions & 8 deletions language/visitor/visitor.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package visitor

import (
"encoding/json"
"reflect"

"fmt"
"github.com/graphql-go/graphql/language/ast"
"github.com/graphql-go/graphql/language/typeInfo"
"reflect"
)

const (
Expand Down Expand Up @@ -446,14 +445,63 @@ func convertMap(src interface{}) (dest map[string]interface{}, err error) {
if src == nil {
return
}
var bts []byte
if bts, err = json.Marshal(src); err != nil {

// return if src is already a map
dest, ok := src.(map[string]interface{})
if ok {
return
}
if err = json.Unmarshal(bts, &dest); err != nil {
return

outputMap := make(map[string]interface{})
val := reflect.ValueOf(src)

// Dereference pointer if necessary
if val.Kind() == reflect.Ptr {
if val.IsNil() {
return nil, fmt.Errorf("input is a nil pointer")
}
val = val.Elem()
}

if val.Kind() != reflect.Struct {
return nil, fmt.Errorf("input is not a struct or pointer to struct")
}
return

typ := val.Type()
for i := 0; i < val.NumField(); i++ {
field := val.Field(i)
fieldName := typ.Field(i).Name

switch field.Kind() {
case reflect.Ptr:
if field.IsNil() {
outputMap[fieldName] = nil
} else {
nestedMap, err := convertMap(field.Interface())
if err != nil {
return nil, err
}
outputMap[fieldName] = nestedMap
}
case reflect.Struct:
nestedMap, err := convertMap(field.Interface())
if err != nil {
return nil, err
}
outputMap[fieldName] = nestedMap
case reflect.Interface:
if field.IsNil() {
outputMap[fieldName] = nil
} else {
concreteValue := field.Elem()
outputMap[fieldName], _ = convertMap(concreteValue.Interface())
}
default:
outputMap[fieldName] = field.Interface()
}
}

return outputMap, nil
}

// get value by key from struct | slice | map | wrap(prev)
Expand Down