-
Notifications
You must be signed in to change notification settings - Fork 4
Faster version of the field selection merging validation #12
Faster version of the field selection merging validation #12
Conversation
The build is only failing for scala 2.11, probably due to a difference in type inference. Is scala 2.11 still required to be supported and shall we update this PR? |
The build can also be flaky. I triggered it again. |
Nope, we have a compilation on scala 2.11. By the way, great article! |
Yes removing 2.11 is a much bigger conversation. We have a large legacy system still on 2.11, so we still need it. |
This compiles on all the supported versions now and is ready for review. |
The latest build error seems to be unrelated to this PR, could you please retrigger the build? |
Unfortunately according to our benchmarks the version with the scala collections is quite a bit slower in the non-asymptotic case than the original one with mutable Java collections. What is your stance regarding this? I would prefer to go back to the Java collections and possibly use anonymous class callbacks instead of lambdas, as scala-2.11 doesn't support lambda SAM syntax yet. |
I trust your decision here. |
It seems to be mostly related to LinkedHashMap / LinkedHashSet performance in scala. I see there is also an open issue regarding their implementation here: scala/bug#11369 If I find the time, I will revert / refactor this tomorrow. In the meantime, is there anything else you would need to get this merged? |
time... 😉 |
Implements a faster version of OverlappingFieldsCanBeMerged, that can deal with a high number of fragments or selection sets without a blowup in runtime. Also includes JMH for benchmarks. The implementation uses Java collections as: - The scala LinkedHashSet implementation is slow - Java util.ArrayList does not preallocate the array The anonymous class syntax for consumers and functions is necessary for compatiblity with scala 2.11, which does not support SAM lambda syntax yet. It can be refactored to use lambda, when scala 2.11 support is dropped. Refs: https://tech.xing.com/graphql-overlapping-fields-can-be-merged-fast-ea6e92e0a01
d4fa9b9
to
b3691b1
Compare
I would again ask you to restart the build, as it is an ArrayOutOfBounds exception that does not seem related to the code. Regarding the changes, I reverted back to using Java collections and for scala 2.11 compatibility use anonymous classes instead of lambdas in the higher order functions. Java collections seem currently the better choice for this, as:
Thanks for taking the time to review this rather big PR! |
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.
General question: how can people use this new implementation?
Should we find an alternative name to OverlappingFieldsCanBeMergedFast
?
Does it differ from OverlappingFieldsCanBeMerged
"just" by its speed, and does it have a different behavior?
build.sbt
Outdated
classDirectory in Jmh := (classDirectory in Test).value | ||
dependencyClasspath in Jmh := (dependencyClasspath in Test).value | ||
compile in Jmh := (compile in Jmh).dependsOn(compile in Test).value | ||
run in Jmh := (run in Jmh).dependsOn(compile in Jmh).evaluated |
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.
I think it's better to put the benchmarks into a separated module
And then the JMH plugin could only be activated for the benchmarks.
Ex: https://github.com/circe/circe/blob/6d2e2dddc42c7b38f5ed35527d5caad8b33bff35/build.sbt#L476-L487
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.
Makes sense, I will have a look at this.
src/main/scala/sangria/validation/rules/overlappingfields/OutputName.scala
Outdated
Show resolved
Hide resolved
|
||
class OverlappingFieldsCanBeMergedFastSpec extends WordSpec with ValidationSupport { | ||
|
||
override val defaultRule = Some(new OverlappingFieldsCanBeMergedFast) |
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.
General question:
if I try this tests with the current implementation (override val defaultRule = Some(new OverlappingFieldsCanBeMerged)
, I have some errors.
Is it expected?
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.
While the rules do implement the same validation, they differ in how they report the errors, so they cannot use the same set of tests. See my answer to your general questions below for more on this.
Hi Yann, these questions all make a lot of sense. I'll answer the general ones here:
|
ok 👍
I very appreciate this. |
…utName.scala Co-Authored-By: Yann Simon <yann.simon.fr@gmail.com>
I added an example of how to use the new validation rule to the PR description. |
@yanns Thanks for merging the other PR. I plan to update this one to the new structure next week. |
…tion # Conflicts: # build.sbt
I updated the PR to the new project structure. Please have another look. |
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.
The PR is looking good to me. Thx for all your efforts.
I just have a question about introducing an annotation for api that may change in the future.
* | ||
* The algorithm is described in [[CachedCheck]]. | ||
*/ | ||
class OverlappingFieldsCanBeMergedFast extends ValidationRule { |
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.
What is your opinion on adding an annotation like akka is doing with@ApiMayChange
so that we can rename it in the future?
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.
I would be fine with that. Is there already an established convention how to signify that in sangria?
Ultimately I hope this can replace the previous rule, so the option to choose explicitly could also disappear at some point.
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.
Thinking about this, I would probably prefer using packages for this type of information, as an annotation can go unnoticed by the client, while a package like "internal" or "experimental" has to be referenced in the import by a client. So anyone importing something from an "experimental" package states that he knows what he is doing.
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.
I would be fine with that. Is there already an established convention how to signify that in sangria?
I don't think there is an existing convention.
I'd recommend to "copy" what others are doing, like in the akka project, unless someone has a better idea.
Ultimately I hope this can replace the previous rule, so the option to choose explicitly could also disappear at some point.
👍
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.
What would be the expectation when using @ApiMayChange
? Does it still obey semantic versioning?
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.
I'd leave the decision here to you and the other maintainers. Maybe there is a way that we could circumvent the problem and come up with a better name? @ApiMayChange
is something I am not particularly fond of, due to how it allows invisible exceptions to semantic versioning. A separately versioned contrib
module from which code then is migrated to core
could be a clearer solution. But to be honest I'd prefer to get this rule in without that overhead.
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.
I'd leave the decision here to you and the other maintainers. Maybe there is a way that we could circumvent the problem and come up with a better name?
@ApiMayChange
is something I am not particularly fond of, due to how it allows invisible exceptions to semantic versioning. A separately versionedcontrib
module from which code then is migrated tocore
could be a clearer solution. But to be honest I'd prefer to get this rule in without that overhead.
I'm not the "maintainer", just giving some of my time to help.
I also think a separately versioned contrib
module would be cleaner.
But giving the time we all can give, I'd suggest to go with the @ApiMayChange
annotation for now so that we can merge this.
- introduce an experimental package and move the new rule there - rename OverlappingFieldsCanBeMergedFast to OverlappingFieldsCanBeMerged as the naming conflict is resolved through the new experimental package - add an @ApiMayChange annotation
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.
Thx a lot!! 🏆
Can you please update the PR comment with the new package name?
@yanns Done |
What a great work (technically & also explaining with the blog post) 🥇 |
The current OverlappingFieldsCanBeMerged validation has performance problems with a high number of fragments or selection sets. This implements a faster version of OverlappingFieldsCanBeMerged, that can deal with a high number of fragments or selection sets without a blowup in runtime. This PR does not remove the old validation yet but instead adds the new one as an additional option to use.
It also includes JMH for benchmarks.
Fixes: sangria-graphql#296
The algorithm is described in:
https://tech.xing.com/graphql-overlapping-fields-can-be-merged-fast-ea6e92e0a01
Below is an example benchmark graph showing the performance improvement for multiple fragments in the same selection set.
The PR has been migrated from the one in the original sangria repository.
To use the new validation rule you have to construct a custom query validator that includes it: