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
Reduce calculation for fragments in ExecutableNormalizedOperation #2911
Conversation
return resolvedTypeCondition; | ||
} else if (currentOnes.size() == 1 && resolvedTypeCondition.contains(currentOnes.iterator().next())) { | ||
return currentOnes; | ||
} |
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.
Java shits me on how access to a first member is that god awful collection.iterator().next()
But here we are!
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.
Perhaps create a utitlity method in graphql.util.FpKit
FpKit. intersection(
that does this optimisation for same type sets
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.
That's a good idea I'll stick it in FpKit
instead
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.
Add tests for the new intersection method
return Sets.intersection(set1, set2); | ||
} | ||
return Sets.intersection(set2, set1); | ||
} |
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.
There should be a test for this. I know its simple. So lock it in with a test
After parsing and validating an incoming GraphQL operation, the engine creates a normalized version of that operation, the
ExecutableNormalizedOperation
.For fragments, there is a little more work involved to determine the possible types. Inside
narrowDownPossibleObjects
, there is a set intersection between the current set of possible objects and the set of types from the resolved type condition.This set intersection can be expensive for very large queries with hundreds of fragments. This PR includes one such example.
In almost every case in the example query, one of the sets being compared only has one member. For example, the resolved types set often has only 1 member, because an inline fragment on a concrete type has only one possible type. It would be equivalent, and much cheaper, to calculate via Set
contains
rather thanintersection
.And I've added a more general tweak to always pass the smallest set first to Guava's
Sets.intersection
. The implementation is faster when the first set is smaller.Benchmark results
Baseline
Optimised
Note: For throughput, a higher number is better. For average time, a lower number is better.