-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Improved access speed of isPossibleType #4040
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
Changes from all commits
eb7f62e
88057b0
04cbbd6
eaf6e40
e08fc0a
3e82b74
21ac5c9
d0cbc63
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| BRANCH=$(git rev-parse --abbrev-ref HEAD) | ||
| JAR="build/libs/graphql-java-0.0.0-$BRANCH-SNAPSHOT-jmh.jar" | ||
| echo "build and then running jmh for $JAR" | ||
|
|
||
| ./gradlew clean jmhJar | ||
|
|
||
| java -jar "$JAR" "$@" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| package benchmark; | ||
|
|
||
| import graphql.schema.GraphQLSchema; | ||
| import graphql.schema.idl.RuntimeWiring; | ||
| import graphql.schema.idl.SchemaGenerator; | ||
| import graphql.schema.idl.SchemaParser; | ||
| import graphql.schema.idl.TypeDefinitionRegistry; | ||
| import org.openjdk.jmh.annotations.Benchmark; | ||
| import org.openjdk.jmh.annotations.BenchmarkMode; | ||
| import org.openjdk.jmh.annotations.Fork; | ||
| import org.openjdk.jmh.annotations.Measurement; | ||
| import org.openjdk.jmh.annotations.Mode; | ||
| import org.openjdk.jmh.annotations.OutputTimeUnit; | ||
| import org.openjdk.jmh.annotations.Warmup; | ||
| import org.openjdk.jmh.infra.Blackhole; | ||
| import org.openjdk.jmh.runner.Runner; | ||
| import org.openjdk.jmh.runner.RunnerException; | ||
| import org.openjdk.jmh.runner.options.Options; | ||
| import org.openjdk.jmh.runner.options.OptionsBuilder; | ||
|
|
||
| import java.util.concurrent.TimeUnit; | ||
|
|
||
| import static benchmark.BenchmarkUtils.runInToolingForSomeTimeThenExit; | ||
|
|
||
| /** | ||
| * This JMH | ||
| */ | ||
| @Warmup(iterations = 2, time = 5) | ||
| @Measurement(iterations = 3) | ||
| @Fork(3) | ||
| public class CreateExtendedSchemaBenchmark { | ||
|
|
||
| private static final String SDL = mkSDL(); | ||
|
|
||
| @Benchmark | ||
| @BenchmarkMode(Mode.Throughput) | ||
| @OutputTimeUnit(TimeUnit.MINUTES) | ||
| public void benchmarkLargeSchemaCreate(Blackhole blackhole) { | ||
| blackhole.consume(createSchema(SDL)); | ||
| } | ||
|
|
||
| @Benchmark | ||
| @BenchmarkMode(Mode.AverageTime) | ||
| @OutputTimeUnit(TimeUnit.MILLISECONDS) | ||
| public void benchmarkLargeSchemaCreateAvgTime(Blackhole blackhole) { | ||
| blackhole.consume(createSchema(SDL)); | ||
| } | ||
|
|
||
| private static GraphQLSchema createSchema(String sdl) { | ||
| TypeDefinitionRegistry registry = new SchemaParser().parse(sdl); | ||
| return new SchemaGenerator().makeExecutableSchema(registry, RuntimeWiring.MOCKED_WIRING); | ||
| } | ||
|
|
||
| /* something like | ||
| type Query { q : String } interface I { f : String } | ||
| interface I1 implements I { | ||
| f : String | ||
| f1 : String | ||
| } | ||
| type O1_1 implements I1 & I { | ||
| f : String | ||
| f1 : String | ||
| } | ||
| type O1_2 implements I1 & I { | ||
| f : String | ||
| f1 : String | ||
| } | ||
| */ | ||
| private static String mkSDL() { | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a benchmark with lots of |
||
| int numTypes = 10000; | ||
| int numExtends = 10; | ||
|
|
||
| StringBuilder sb = new StringBuilder(); | ||
| sb.append("type Query { q : String } interface I { f : String } interface X { x : String }\n"); | ||
| for (int i = 0; i < numTypes; i++) { | ||
| sb.append("interface I").append(i).append(" implements I { \n") | ||
| .append("\tf : String \n") | ||
| .append("\tf").append(i).append(" : String \n").append("}\n"); | ||
|
|
||
| sb.append("type O").append(i).append(" implements I").append(i).append(" & I { \n") | ||
| .append("\tf : String \n") | ||
| .append("\tf").append(i).append(" : String \n") | ||
| .append("}\n"); | ||
|
|
||
| sb.append("extend type O").append(i).append(" implements X").append(" { \n") | ||
| .append("\tx : String \n") | ||
| .append("}\n"); | ||
|
|
||
| for (int j = 0; j < numExtends; j++) { | ||
| sb.append("extend type O").append(i).append(" { \n") | ||
| .append("\textendedF").append(j).append(" : String \n") | ||
| .append("}\n"); | ||
|
|
||
| } | ||
| } | ||
| return sb.toString(); | ||
| } | ||
|
|
||
| public static void main(String[] args) throws RunnerException { | ||
| try { | ||
| runAtStartup(); | ||
| } catch (Throwable e) { | ||
| throw new RuntimeException(e); | ||
| } | ||
| Options opt = new OptionsBuilder() | ||
| .include("benchmark.CreateExtendedSchemaBenchmark") | ||
| .build(); | ||
|
|
||
| new Runner(opt).run(); | ||
| } | ||
|
|
||
| private static void runAtStartup() { | ||
| runInToolingForSomeTimeThenExit( | ||
| () -> { | ||
| }, | ||
| () -> createSchema(SDL), | ||
| () -> { | ||
| } | ||
| ); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,7 +29,7 @@ | |
| import java.util.HashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Optional; | ||
| import java.util.Objects; | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Getting rid of the Optional methods and using the getOrNull ones |
||
| import java.util.Set; | ||
| import java.util.function.BinaryOperator; | ||
| import java.util.function.Function; | ||
|
|
@@ -73,7 +73,7 @@ void checkImplementingTypes(List<GraphQLError> errors, TypeDefinitionRegistry ty | |
| private void checkImplementingType( | ||
| List<GraphQLError> errors, | ||
| TypeDefinitionRegistry typeRegistry, | ||
| ImplementingTypeDefinition type) { | ||
| ImplementingTypeDefinition<?> type) { | ||
|
|
||
| Map<InterfaceTypeDefinition, ImplementingTypeDefinition> implementedInterfaces = | ||
| checkInterfacesNotImplementedMoreThanOnce(errors, type, typeRegistry); | ||
|
|
@@ -172,7 +172,7 @@ private void checkInterfaceIsImplemented( | |
|
|
||
| private void checkArgumentConsistency( | ||
| String typeOfType, | ||
| ImplementingTypeDefinition objectTypeDef, | ||
| ImplementingTypeDefinition<?> objectTypeDef, | ||
| InterfaceTypeDefinition interfaceTypeDef, | ||
| FieldDefinition objectFieldDef, | ||
| FieldDefinition interfaceFieldDef, | ||
|
|
@@ -211,7 +211,7 @@ private void checkArgumentConsistency( | |
| } | ||
|
|
||
| private Map<InterfaceTypeDefinition, List<ImplementingTypeDefinition>> getLogicallyImplementedInterfaces( | ||
| ImplementingTypeDefinition type, | ||
| ImplementingTypeDefinition<?> type, | ||
| TypeDefinitionRegistry typeRegistry | ||
| ) { | ||
|
|
||
|
|
@@ -255,18 +255,17 @@ private <T> BinaryOperator<T> mergeFirstValue() { | |
| return (v1, v2) -> v1; | ||
| } | ||
|
|
||
| private Optional<InterfaceTypeDefinition> toInterfaceTypeDefinition(Type type, TypeDefinitionRegistry typeRegistry) { | ||
| private InterfaceTypeDefinition toInterfaceTypeDefinition(Type<?> type, TypeDefinitionRegistry typeRegistry) { | ||
| TypeInfo typeInfo = TypeInfo.typeInfo(type); | ||
| TypeName unwrapped = typeInfo.getTypeName(); | ||
|
|
||
| return typeRegistry.getType(unwrapped, InterfaceTypeDefinition.class); | ||
| return typeRegistry.getTypeOrNull(unwrapped, InterfaceTypeDefinition.class); | ||
| } | ||
|
|
||
| private Set<InterfaceTypeDefinition> toInterfaceTypeDefinitions(TypeDefinitionRegistry typeRegistry, Collection<Type> implementsTypes) { | ||
| return implementsTypes.stream() | ||
| .map(t -> toInterfaceTypeDefinition(t, typeRegistry)) | ||
| .filter(Optional::isPresent) | ||
| .map(Optional::get) | ||
| .filter(Objects::nonNull) | ||
| .collect(toSet()); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,7 +34,6 @@ | |
| import java.util.LinkedHashSet; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Optional; | ||
| import java.util.Set; | ||
| import java.util.function.BiFunction; | ||
| import java.util.function.Consumer; | ||
|
|
@@ -333,17 +332,19 @@ private void checkFieldTypesPresent(TypeDefinitionRegistry typeRegistry, List<Gr | |
|
|
||
| private Consumer<Type> checkTypeExists(String typeOfType, TypeDefinitionRegistry typeRegistry, List<GraphQLError> errors, TypeDefinition typeDefinition) { | ||
| return t -> { | ||
| TypeName unwrapped = TypeInfo.typeInfo(t).getTypeName(); | ||
| if (!typeRegistry.hasType(unwrapped)) { | ||
| String name = TypeInfo.typeName(t); | ||
| if (!typeRegistry.hasType(name)) { | ||
| TypeName unwrapped = TypeInfo.typeInfo(t).getTypeName(); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. faster look up - we only create a TypeInfo if its in error |
||
| errors.add(new MissingTypeError(typeOfType, typeDefinition, unwrapped)); | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| private Consumer<Type> checkTypeExists(TypeDefinitionRegistry typeRegistry, List<GraphQLError> errors, String typeOfType, Node element, String elementName) { | ||
| return ivType -> { | ||
| TypeName unwrapped = TypeInfo.typeInfo(ivType).getTypeName(); | ||
| if (!typeRegistry.hasType(unwrapped)) { | ||
| String name = TypeInfo.typeName(ivType); | ||
| if (!typeRegistry.hasType(name)) { | ||
| TypeName unwrapped = TypeInfo.typeInfo(ivType).getTypeName(); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. faster look up - we only create a TypeInfo if its in error |
||
| errors.add(new MissingTypeError(typeOfType, element, elementName, unwrapped)); | ||
| } | ||
| }; | ||
|
|
@@ -353,10 +354,10 @@ private Consumer<? super Type> checkInterfaceTypeExists(TypeDefinitionRegistry t | |
| return t -> { | ||
| TypeInfo typeInfo = TypeInfo.typeInfo(t); | ||
| TypeName unwrapped = typeInfo.getTypeName(); | ||
| Optional<TypeDefinition> type = typeRegistry.getType(unwrapped); | ||
| if (!type.isPresent()) { | ||
| TypeDefinition<?> type = typeRegistry.getTypeOrNull(unwrapped); | ||
| if (type == null) { | ||
| errors.add(new MissingInterfaceTypeError("interface", typeDefinition, unwrapped)); | ||
| } else if (!(type.get() instanceof InterfaceTypeDefinition)) { | ||
| } else if (!(type instanceof InterfaceTypeDefinition)) { | ||
| errors.add(new MissingInterfaceTypeError("interface", typeDefinition, unwrapped)); | ||
| } | ||
| }; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A little helper to make it easier to run the JMH tests on the command line