Skip to content

Avoid using CompletableFuture.whenCompleteAsync() #1440

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

Merged
merged 1 commit into from
Nov 15, 2018

Conversation

trustin
Copy link
Member

@trustin trustin commented Nov 15, 2018

Related: #1426

Motivation:

CompletableFuture always creates a new CompletionException after it
calls the callback registered with whenCompleteAsync(), even if there
are no dependants and the CompletionException will never be used.

See https://hg.openjdk.java.net/jdk/jdk11/file/1ddf9a99e4ad/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java#l870
for more information.

Modifications:

  • Use CompletableFuture.handleAsync() instead of whenCompleteAsync().
  • Miscellaneous:
    • Avoid using voidFunction() which increases the level of indirection

Result:

master:

Benchmark                        (clientType)   Mode  Cnt      Score     Error  Units
DownstreamSimpleBenchmark.empty        NORMAL  thrpt  100  52167.567 ± 274.358  ops/s

This pull request:

Benchmark                        (clientType)   Mode  Cnt      Score     Error  Units
DownstreamSimpleBenchmark.empty        NORMAL  thrpt  100  58171.594 ± 365.014  ops/s

@trustin trustin added this to the 0.76.0 milestone Nov 15, 2018
Copy link
Contributor

@minwoox minwoox left a comment

Choose a reason for hiding this comment

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

Great job~!

@trustin trustin force-pushed the no_whencomplete branch 4 times, most recently from 91de14a to bc989d9 Compare November 15, 2018 03:15
Copy link
Collaborator

@anuraaga anuraaga left a comment

Choose a reason for hiding this comment

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

Lots of performance for free - will take it!

Copy link
Contributor

@hyangtack hyangtack left a comment

Choose a reason for hiding this comment

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

Great job!

Related: line#1426

Motivation:

`CompletableFuture` always creates a new `CompletionException` after it
calls the callback registered with `whenCompleteAsync()`, even if there
are no dependants and the `CompletionException` will never be used.

See https://hg.openjdk.java.net/jdk/jdk11/file/1ddf9a99e4ad/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java#l870
for more information.

Modifications:

- Use `CompletableFuture.handleAsync()` instead of `whenCompleteAsync()`.
- Miscellaneous:
  - Avoid using `voidFunction()` which increases the level of indirection

Result:

- Fixes line#1426
- Better performance

master:

    Benchmark                        (clientType)   Mode  Cnt      Score     Error  Units
    DownstreamSimpleBenchmark.empty        NORMAL  thrpt  100  52167.567 ± 274.358  ops/s

This pull request:

    Benchmark                        (clientType)   Mode  Cnt      Score     Error  Units
    DownstreamSimpleBenchmark.empty        NORMAL  thrpt  100  58171.594 ± 365.014  ops/s
@codecov
Copy link

codecov bot commented Nov 15, 2018

Codecov Report

Merging #1440 into master will decrease coverage by 0.05%.
The diff coverage is 87.69%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1440      +/-   ##
==========================================
- Coverage   72.62%   72.57%   -0.06%     
==========================================
  Files         617      617              
  Lines       26820    26832      +12     
  Branches     3245     3245              
==========================================
- Hits        19477    19472       -5     
- Misses       5636     5655      +19     
+ Partials     1707     1705       -2
Impacted Files Coverage Δ
...ecorp/armeria/server/grpc/UnframedGrpcService.java 82.4% <100%> (ø) ⬆️
.../linecorp/armeria/client/Http2ResponseDecoder.java 59.09% <100%> (+0.37%) ⬆️
.../java/com/linecorp/armeria/common/HttpRequest.java 70.21% <100%> (ø) ⬆️
...dpoint/healthcheck/HealthCheckedEndpointGroup.java 79.03% <100%> (ø) ⬆️
.../com/linecorp/armeria/server/grpc/GrpcService.java 94.87% <100%> (ø) ⬆️
...com/linecorp/armeria/server/HttpServerHandler.java 77.17% <100%> (+1.11%) ⬆️
...java/com/linecorp/armeria/common/HttpResponse.java 83.03% <100%> (ø) ⬆️
...linecorp/armeria/common/util/StartStopSupport.java 95.83% <100%> (ø) ⬆️
...ia/client/circuitbreaker/CircuitBreakerClient.java 90% <100%> (+0.34%) ⬆️
...inecorp/armeria/client/grpc/ArmeriaClientCall.java 81.67% <100%> (+1.52%) ⬆️
... and 19 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4a138af...93df38b. Read the comment docs.

@trustin trustin merged commit 796bee8 into line:master Nov 15, 2018
@trustin trustin deleted the no_whencomplete branch November 15, 2018 04:36
trustin added a commit to trustin/armeria that referenced this pull request Nov 16, 2018
@trustin
Copy link
Member Author

trustin commented Nov 16, 2018

Ran the benchmark again today for #1444 and the throughput of this pull request is now around 54,000-56,000. Maybe not as dramatic as initially observed, although it's still quite an improvement.

trustin added a commit to trustin/armeria that referenced this pull request Feb 15, 2019
Motivation:

As we discovered in line#1440, `whenComplete()` is harmful for performance.

Modifications:

- Use `handle()` instead of `whenComplete()`

Result:

- Potentially less unnecessary instantiation of `CompletionException`.
trustin added a commit that referenced this pull request Feb 15, 2019
Motivation:

As we discovered in #1440, `whenComplete()` is harmful for performance.

Modifications:

- Use `handle()` instead of `whenComplete()`

Result:

- Potentially less unnecessary instantiation of `CompletionException`.
@trustin trustin mentioned this pull request Aug 18, 2020
fmguerreiro pushed a commit to fmguerreiro/armeria that referenced this pull request Sep 19, 2020
Related: line#1426

Motivation:

`CompletableFuture` always creates a new `CompletionException` after it
calls the callback registered with `whenCompleteAsync()`, even if there
are no dependants and the `CompletionException` will never be used.

See https://hg.openjdk.java.net/jdk/jdk11/file/1ddf9a99e4ad/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java#l870
for more information.

Modifications:

- Use `CompletableFuture.handleAsync()` instead of `whenCompleteAsync()`.
- Miscellaneous:
  - Avoid using `voidFunction()` which increases the level of indirection

Result:

- Fixes line#1426
- Better performance

master:

    Benchmark                        (clientType)   Mode  Cnt      Score     Error  Units
    DownstreamSimpleBenchmark.empty        NORMAL  thrpt  100  52167.567 ± 274.358  ops/s

This pull request:

    Benchmark                        (clientType)   Mode  Cnt      Score     Error  Units
    DownstreamSimpleBenchmark.empty        NORMAL  thrpt  100  58171.594 ± 365.014  ops/s
fmguerreiro pushed a commit to fmguerreiro/armeria that referenced this pull request Sep 19, 2020
fmguerreiro pushed a commit to fmguerreiro/armeria that referenced this pull request Sep 19, 2020
Motivation:

As we discovered in line#1440, `whenComplete()` is harmful for performance.

Modifications:

- Use `handle()` instead of `whenComplete()`

Result:

- Potentially less unnecessary instantiation of `CompletionException`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants