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

Avoiding Async array copies #2839

Merged
merged 1 commit into from Jun 8, 2022

Conversation

dfa1
Copy link
Contributor

@dfa1 dfa1 commented May 28, 2022

@bbakerman @andimarek hi guys :)

while profiling in YourKit, I spotted some extra array allocations for CompletableFuture. This is still an idea... and a work in progress... please have a look :-) There is a special handling for SelectionSet of only 1 field: in this case the array allocation could be removed completely.

Baseline:

    Benchmark                                    Mode  Cnt   Score   Error  Units
    BenchMark.benchMarkSimpleQueriesThroughput  thrpt   15  52.398 ± 0.944  ops/s
    BenchMark.benchMarkSimpleQueriesAvgTime      avgt   15  19.028 ± 0.376  ms/op

After this PR:

    Benchmark                                    Mode  Cnt   Score   Error  Units
    BenchMark.benchMarkSimpleQueriesThroughput  thrpt   15  55.134 ± 0.782  ops/s
    BenchMark.benchMarkSimpleQueriesAvgTime      avgt   15  17.925 ± 0.505  ms/op

is about 5-6% better on my machine (that is quite old, so maybe it is less on newer machines). Do you see other hot spots where this could beneficial?

Copy link
Member

@bbakerman bbakerman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall I approve of this approach. We can know up front how many CFs we have and hence this will stop a list allocation which gets turned into an array allocation. We can go straight to an array allocation of the right size.

It would be interesting to see if ImmutableList.Builder on the returned results ended up faster of slow - it depends on the lifetime of the objects involved of course and how often they get copied into some other list

src/main/java/graphql/execution/Async.java Show resolved Hide resolved
src/main/java/graphql/execution/Async.java Outdated Show resolved Hide resolved
overallResult.completeExceptionally(exception);
return;
}
List<T> results = Collections.singletonList(completableFuture.join());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use ImmutabeList.of() -we prefer the guava lists where possible

src/main/java/graphql/execution/Async.java Show resolved Hide resolved
@dfa1 dfa1 force-pushed the performance-async-object branch from 063dc72 to 552e2df Compare May 30, 2022 05:40
A typed interface to build CompletableFuture.allOf without intermediate
List allocations.
@dfa1 dfa1 force-pushed the performance-async-object branch from aba559d to 8e62993 Compare May 30, 2022 18:25
@dfa1
Copy link
Contributor Author

dfa1 commented May 30, 2022

@bbakerman please have another look, I should have covered all your inputs...
and I just squashed the commits to have a clean history ;)

@bbakerman bbakerman added this to the 19.0 milestone Jun 8, 2022
@bbakerman bbakerman merged commit 9da87e2 into graphql-java:master Jun 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants