-
Notifications
You must be signed in to change notification settings - Fork 840
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #268 from mrhenry/benchmarks
Add benchmarks
- Loading branch information
Showing
4 changed files
with
379 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package benchutil | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/graphql-go/graphql" | ||
) | ||
|
||
type color struct { | ||
Hex string | ||
R int | ||
G int | ||
B int | ||
} | ||
|
||
func ListSchemaWithXItems(x int) graphql.Schema { | ||
|
||
list := generateXListItems(x) | ||
|
||
color := graphql.NewObject(graphql.ObjectConfig{ | ||
Name: "Color", | ||
Description: "A color", | ||
Fields: graphql.Fields{ | ||
"hex": &graphql.Field{ | ||
Type: graphql.NewNonNull(graphql.String), | ||
Description: "Hex color code.", | ||
Resolve: func(p graphql.ResolveParams) (interface{}, error) { | ||
if c, ok := p.Source.(color); ok { | ||
return c.Hex, nil | ||
} | ||
return nil, nil | ||
}, | ||
}, | ||
"r": &graphql.Field{ | ||
Type: graphql.NewNonNull(graphql.Int), | ||
Description: "Red value.", | ||
Resolve: func(p graphql.ResolveParams) (interface{}, error) { | ||
if c, ok := p.Source.(color); ok { | ||
return c.R, nil | ||
} | ||
return nil, nil | ||
}, | ||
}, | ||
"g": &graphql.Field{ | ||
Type: graphql.NewNonNull(graphql.Int), | ||
Description: "Green value.", | ||
Resolve: func(p graphql.ResolveParams) (interface{}, error) { | ||
if c, ok := p.Source.(color); ok { | ||
return c.G, nil | ||
} | ||
return nil, nil | ||
}, | ||
}, | ||
"b": &graphql.Field{ | ||
Type: graphql.NewNonNull(graphql.Int), | ||
Description: "Blue value.", | ||
Resolve: func(p graphql.ResolveParams) (interface{}, error) { | ||
if c, ok := p.Source.(color); ok { | ||
return c.B, nil | ||
} | ||
return nil, nil | ||
}, | ||
}, | ||
}, | ||
}) | ||
|
||
queryType := graphql.NewObject(graphql.ObjectConfig{ | ||
Name: "Query", | ||
Fields: graphql.Fields{ | ||
"colors": { | ||
Type: graphql.NewList(color), | ||
Resolve: func(p graphql.ResolveParams) (interface{}, error) { | ||
return list, nil | ||
}, | ||
}, | ||
}, | ||
}) | ||
|
||
colorSchema, _ := graphql.NewSchema(graphql.SchemaConfig{ | ||
Query: queryType, | ||
}) | ||
|
||
return colorSchema | ||
} | ||
|
||
var colors []color | ||
|
||
func init() { | ||
colors = make([]color, 0, 256*16*16) | ||
|
||
for r := 0; r < 256; r++ { | ||
for g := 0; g < 16; g++ { | ||
for b := 0; b < 16; b++ { | ||
colors = append(colors, color{ | ||
Hex: fmt.Sprintf("#%x%x%x", r, g, b), | ||
R: r, | ||
G: g, | ||
B: b, | ||
}) | ||
} | ||
} | ||
} | ||
} | ||
|
||
func generateXListItems(x int) []color { | ||
if x > len(colors) { | ||
x = len(colors) | ||
} | ||
return colors[0:x] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
package benchutil | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/graphql-go/graphql" | ||
) | ||
|
||
func WideSchemaWithXFieldsAndYItems(x int, y int) graphql.Schema { | ||
wide := graphql.NewObject(graphql.ObjectConfig{ | ||
Name: "Wide", | ||
Description: "An object", | ||
Fields: generateXWideFields(x), | ||
}) | ||
|
||
queryType := graphql.NewObject(graphql.ObjectConfig{ | ||
Name: "Query", | ||
Fields: graphql.Fields{ | ||
"wide": { | ||
Type: graphql.NewList(wide), | ||
Resolve: func(p graphql.ResolveParams) (interface{}, error) { | ||
out := make([]struct{}, 0, y) | ||
for i := 0; i < y; i++ { | ||
out = append(out, struct{}{}) | ||
} | ||
return out, nil | ||
}, | ||
}, | ||
}, | ||
}) | ||
|
||
wideSchema, _ := graphql.NewSchema(graphql.SchemaConfig{ | ||
Query: queryType, | ||
}) | ||
|
||
return wideSchema | ||
} | ||
|
||
func generateXWideFields(x int) graphql.Fields { | ||
fields := graphql.Fields{} | ||
for i := 0; i < x; i++ { | ||
fields[generateFieldNameFromX(i)] = generateWideFieldFromX(i) | ||
} | ||
return fields | ||
} | ||
|
||
func generateWideFieldFromX(x int) *graphql.Field { | ||
return &graphql.Field{ | ||
Type: generateWideTypeFromX(x), | ||
Resolve: generateWideResolveFromX(x), | ||
} | ||
} | ||
|
||
func generateWideTypeFromX(x int) graphql.Type { | ||
switch x % 8 { | ||
case 0: | ||
return graphql.String | ||
case 1: | ||
return graphql.NewNonNull(graphql.String) | ||
case 2: | ||
return graphql.Int | ||
case 3: | ||
return graphql.NewNonNull(graphql.Int) | ||
case 4: | ||
return graphql.Float | ||
case 5: | ||
return graphql.NewNonNull(graphql.Float) | ||
case 6: | ||
return graphql.Boolean | ||
case 7: | ||
return graphql.NewNonNull(graphql.Boolean) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func generateFieldNameFromX(x int) string { | ||
var out string | ||
alphabet := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "z"} | ||
v := x | ||
for { | ||
r := v % 10 | ||
out = alphabet[r] + out | ||
v = v / 10 | ||
if v == 0 { | ||
break | ||
} | ||
} | ||
return out | ||
} | ||
|
||
func generateWideResolveFromX(x int) func(p graphql.ResolveParams) (interface{}, error) { | ||
switch x % 8 { | ||
case 0: | ||
return func(p graphql.ResolveParams) (interface{}, error) { | ||
return fmt.Sprint(x), nil | ||
} | ||
case 1: | ||
return func(p graphql.ResolveParams) (interface{}, error) { | ||
return fmt.Sprint(x), nil | ||
} | ||
case 2: | ||
return func(p graphql.ResolveParams) (interface{}, error) { | ||
return x, nil | ||
} | ||
case 3: | ||
return func(p graphql.ResolveParams) (interface{}, error) { | ||
return x, nil | ||
} | ||
case 4: | ||
return func(p graphql.ResolveParams) (interface{}, error) { | ||
return float64(x), nil | ||
} | ||
case 5: | ||
return func(p graphql.ResolveParams) (interface{}, error) { | ||
return float64(x), nil | ||
} | ||
case 6: | ||
return func(p graphql.ResolveParams) (interface{}, error) { | ||
if x%2 == 0 { | ||
return false, nil | ||
} | ||
return true, nil | ||
} | ||
case 7: | ||
return func(p graphql.ResolveParams) (interface{}, error) { | ||
if x%2 == 0 { | ||
return false, nil | ||
} | ||
return true, nil | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func WideSchemaQuery(x int) string { | ||
var fields string | ||
for i := 0; i < x; i++ { | ||
fields = fields + generateFieldNameFromX(i) + " " | ||
} | ||
|
||
return fmt.Sprintf("query { wide { %s} }", fields) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
package graphql_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/graphql-go/graphql" | ||
"github.com/graphql-go/graphql/benchutil" | ||
) | ||
|
||
type B struct { | ||
Query string | ||
Schema graphql.Schema | ||
} | ||
|
||
func benchGraphql(bench B, p graphql.Params, t testing.TB) { | ||
result := graphql.Do(p) | ||
if len(result.Errors) > 0 { | ||
t.Fatalf("wrong result, unexpected errors: %v", result.Errors) | ||
} | ||
} | ||
|
||
// Benchmark a reasonably large list of small items. | ||
func BenchmarkListQuery_1(b *testing.B) { | ||
nItemsListQueryBenchmark(1)(b) | ||
} | ||
|
||
func BenchmarkListQuery_100(b *testing.B) { | ||
nItemsListQueryBenchmark(100)(b) | ||
} | ||
|
||
func BenchmarkListQuery_1K(b *testing.B) { | ||
nItemsListQueryBenchmark(1000)(b) | ||
} | ||
|
||
func BenchmarkListQuery_10K(b *testing.B) { | ||
nItemsListQueryBenchmark(10 * 1000)(b) | ||
} | ||
|
||
func BenchmarkListQuery_100K(b *testing.B) { | ||
nItemsListQueryBenchmark(100 * 1000)(b) | ||
} | ||
|
||
func nItemsListQueryBenchmark(x int) func(b *testing.B) { | ||
return func(b *testing.B) { | ||
schema := benchutil.ListSchemaWithXItems(x) | ||
|
||
bench := B{ | ||
Query: ` | ||
query { | ||
colors { | ||
hex | ||
r | ||
g | ||
b | ||
} | ||
} | ||
`, | ||
Schema: schema, | ||
} | ||
|
||
for i := 0; i < b.N; i++ { | ||
|
||
params := graphql.Params{ | ||
Schema: schema, | ||
RequestString: bench.Query, | ||
} | ||
benchGraphql(bench, params, b) | ||
} | ||
} | ||
} | ||
|
||
func BenchmarkWideQuery_1_1(b *testing.B) { | ||
nFieldsyItemsQueryBenchmark(1, 1)(b) | ||
} | ||
|
||
func BenchmarkWideQuery_10_1(b *testing.B) { | ||
nFieldsyItemsQueryBenchmark(10, 1)(b) | ||
} | ||
|
||
func BenchmarkWideQuery_100_1(b *testing.B) { | ||
nFieldsyItemsQueryBenchmark(100, 1)(b) | ||
} | ||
|
||
func BenchmarkWideQuery_1K_1(b *testing.B) { | ||
nFieldsyItemsQueryBenchmark(1000, 1)(b) | ||
} | ||
|
||
func BenchmarkWideQuery_1_10(b *testing.B) { | ||
nFieldsyItemsQueryBenchmark(1, 10)(b) | ||
} | ||
|
||
func BenchmarkWideQuery_10_10(b *testing.B) { | ||
nFieldsyItemsQueryBenchmark(10, 10)(b) | ||
} | ||
|
||
func BenchmarkWideQuery_100_10(b *testing.B) { | ||
nFieldsyItemsQueryBenchmark(100, 10)(b) | ||
} | ||
|
||
func BenchmarkWideQuery_1K_10(b *testing.B) { | ||
nFieldsyItemsQueryBenchmark(1000, 10)(b) | ||
} | ||
|
||
func nFieldsyItemsQueryBenchmark(x int, y int) func(b *testing.B) { | ||
return func(b *testing.B) { | ||
schema := benchutil.WideSchemaWithXFieldsAndYItems(x, y) | ||
query := benchutil.WideSchemaQuery(x) | ||
|
||
bench := B{ | ||
Query: query, | ||
Schema: schema, | ||
} | ||
|
||
b.ResetTimer() | ||
|
||
for i := 0; i < b.N; i++ { | ||
params := graphql.Params{ | ||
Schema: schema, | ||
RequestString: bench.Query, | ||
} | ||
benchGraphql(bench, params, b) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters