Save intermediate text encoded buffer copies #5358
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Websocket txt messages perform an additional byte[] copy, because:
Buffer::buffer(String)
is performingString::getBytes
-> first byte[] allocationVertxByteBufAllocator.DEFAULT.heapBuffer
to write the copy in -> second byte[] allocation + copyVertxByteBufAllocator.DEFAULT.heapBuffer
could allocate, based onUnsafe
presence:UnpooledHeapByteBuf
UnpooledUnsafeHeapByteBuf
Both the Vertx childrens of these 2 Netty buffers are NOT exposing directly the ability to wrap a given byte[] and that's why we currently perform the copy: in theory
UnpooledHeapByteBuf
vertx variant could be modified to do it, butUnpooledUnsafeHeapByteBuf
nope, because it doesn't expose its parent constructor which enable setting the byte[] array without copying it (see https://github.com/netty/netty/blob/netty-4.1.114.Final/buffer/src/main/java/io/netty/buffer/UnpooledHeapByteBuf.java#L69).Fixing the additional copy should require to change both Vertx and Netty, for not much gains, given that sharing a given byte[] is likely to disappear in Netty 5, regardless, so, not a good solution.
A different path would be to "guesstimate" the length of the utf8 array (there are 2 Netty method for such: eager O(1) or precise O(n)) - and using Netty's
ByteBuf
encoder to perform it:this could be beneficial, but not ideal because the JVM can perform String checks to estimate the length of the encoded byte[] way faster thanks to its vectorized instructions.
This still could be benchmarked, to make sure, is a valid assumption.
For completeness, this same path is used by https://github.com/eclipse-vertx/vert.x/blob/4.5.10/src/main/java/io/vertx/core/http/impl/WebSocketImplBase.java#L240 which is using
Unpooled::copiedBuffer
under the hood to do what's described above and allocatesio.netty.buffer.UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeHeapByteBuf
orio.netty.buffer.UnpooledByteBufAllocator$InstrumentedUnpooledHeapByteBuf
.The approach taken for this PR is instead to allocates a
UnpooledHeapByteBuf
without performing any copy:String::getBytes
and not performing any additional copy from it (including the wrappersBufferImpl
and subsequent Netty slices