-
Notifications
You must be signed in to change notification settings - Fork 411
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
Improve the Client's performance for non-stream bodies #2919
Improve the Client's performance for non-stream bodies #2919
Conversation
# Conflicts: # zio-http/jvm/src/main/scala/zio/http/netty/AsyncBodyReader.scala # zio-http/jvm/src/main/scala/zio/http/netty/NettyBody.scala
@jdegoes, @987Nabil brought to my attention this issue #2117 after seeing my PR. I think the issue is pretty outdated with a part of it already solved in a previous release. However this PR does improve the Client's performance quite a fair bit. Do you think it's applicable to claim it (or part of it) if I were to add benchmarks to showcase the improvement? It's totally okay if you think it's not related, just thought to ask :) |
@kyri-petrou Yes, adding benchmarks would be great! Complexity can be ignored for 20-40% improvement in performance. |
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 realised that these macros did not work while adding the benchmarks because the fromAbsoluteURI
method is package-private.
I decided to just fix it here instead so that I could use them in the benchmarks
…g-performance' into improve-client-non-streaming-performance
@jdegoes done! See the updated PR description for the results |
❤️ |
/claim #2117
This PR reimplements the way that we "collect" the response body when the user uses
asArray
,asChunk
,asText
etc. (basically any method other thanasStream
).When those methods are used, regardless of whether we use a ZStream or just a plain
ArrayBuilder
as the buffer, we will be materializing the entire body into memory. Therefore, we can avoid all the overheads of ZStream and simply buffer the entire response into the array builder which performs much better.Since we don't have benchmarks for the Client, I don't have any results to show at the moment, but based on some local testing I'm seeing the following:20% improvement of usingasChunk
vsasStream.collectAll
35-40% improvement over the baseline (series/2.x). This is due to some of the optimizations that benefit both streaming and non-streaming bodiesEDIT: Benchmark suite added and results are added below
Note:
The one thing I'm a bit sceptical about this implementation is whether the aggregation should be happening within
UnsafeAsync.Aggregating
instead of withinAsyncBodyReader
. I think semantically it would have been better to have this logic withinUnsafeAsync.Aggregating
, but unfortunately the performance is not as good as doing this within theAsyncBodyReader
since we can't utilize a single ArrayBuilder to buffer the entire response, and so we need to create an intermediate array whenconnect
is called.@jdegoes Let me know what you think. Do we want to prioritise an implementation that performs better or one that it's cleaner/easier to reason with and follow
Benchmark results
TLDR:
asStream
asChunk
/asArray
/asString
🚀Main branch (NOTE: performance of
asChunk
andasStream.runCollect
is the same sinceasChunk
uses a stream under the hood)PR branch: