-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
make ByteAccumulator recyclable to fix issue #5499 #5520
Conversation
ccb3582
to
e2d1eae
Compare
@leonchen83 Thanks for the PR! The ECA check has failed validation for some reason, take a look here for more info: |
57141b4
to
054e18b
Compare
@lachlan-roberts |
10051a6
to
103653f
Compare
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.
Remove the ThreadLocal.
Also, fix your ECA, otherwise we cannot merge this.
.../src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java
Outdated
Show resolved
Hide resolved
.../main/java/org/eclipse/jetty/websocket/common/extensions/compress/DeflateFrameExtension.java
Outdated
Show resolved
Hide resolved
.../java/org/eclipse/jetty/websocket/common/extensions/compress/PerMessageDeflateExtension.java
Outdated
Show resolved
Hide resolved
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.
@leonchen83 @lachlan-roberts I think this is more or less the right approach, but I think more can be done as there is still a fair bit of copying, plus we might end up with lots of max size buffers in the list.
A couple of ideas....
The algorithm in copyChunk
could be:
- if the byte array passed is the last one returned by
newByteArray
- If there are no chunks in the list OR there is not enough free space in last item in list
- just add that array to the list.
- do not let the buffer be returned again by
newByteArray
- else there is room in the last buffer in the list
- copy the data into the free space in the last entry.
- allow the passed buffer to be returned again by next call to
newByteArray
- If there are no chunks in the list OR there is not enough free space in last item in list
- else
- throw IllegalArgumentException
The other thing that could greatly improve this class is to pass the BufferPool to it, so that rather than creation byte arrays, it creates a ByteBuffers with arrays. If the final list only has a single entry, then it can be used as a ByteBuffer rather than with a transferTo
@lachlan-roberts can you work with @leonchen83 to improve this... net necessary as per my suggestions, but do consider them.
@joakime |
@lachlan-roberts is it possible/easy to associate a |
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.
Fix your ECA.
Don't make unrelated changes to this PR please.
.../src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java
Show resolved
Hide resolved
.../src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java
Outdated
Show resolved
Hide resolved
First, fix your ECA. (I cannot stress this enough, don't ignore this). Test this on slow connections, with larger messages split over many frames, on busy ThreadPools and you'll start to see why we don't use ThreadLocal ourselves. |
Hi I'm digging how to fix ECA, sorry but maybe need a little time. |
f0273e2
to
ae95f6d
Compare
The Extensions, like these Compress Extensions, are already 1 unique instance per connection. |
3822961
to
4530d9c
Compare
Ah yes! so no need to pool the BAs in a thread local or anywhere else. Just create one in the connection and the buffers will be reused at least within that connection. A good simple saving without the risk of sharing buffers between connections. |
And if you have 2 extensions present that both need a ByteAccumulator then the current non-ThreadLocal version is still preferred. |
c04a934
to
a98265c
Compare
Hi today I changed following code in this PR
|
@leonchen83 instead of using the |
1fc4f56
to
479883f
Compare
@lachlan-roberts |
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.
We also have access to the ByteBufferPool
from CompressExtension
so this could be used in the ByteAccumulator
.
I think you could pass in the bufferPool in the constructor, then the newByteBuffer
method could use the bufferPool, and all the buffers should be released back to the pool when it is recycled.
.../src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java
Show resolved
Hide resolved
.../src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java
Outdated
Show resolved
Hide resolved
@lachlan-roberts |
e131c7b
to
018722f
Compare
@joakime would you consider |
5a87f3b
to
8b72f13
Compare
@lachlan-roberts |
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.
...on/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/ByteAccumulator.java
Outdated
Show resolved
Hide resolved
...on/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/ByteAccumulator.java
Outdated
Show resolved
Hide resolved
System.arraycopy(buf, offset, copy, 0, length); | ||
|
||
chunks.add(copy); | ||
chunks.add(ByteBuffer.wrap(buf, offset, length)); |
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.
This copyChunk(byte[] buf, int offset, int length)
method doesn't really work with the ByteBufferPool
. This ByteBuffer will eventually be returned to the pool but we have created it right here. I think this will give an error if it is used.
...on/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/ByteAccumulator.java
Outdated
Show resolved
Hide resolved
95f7c04
to
0b22a92
Compare
@lachlan-roberts |
dd0c63c
to
64a4738
Compare
2da50c1
to
7cbe501
Compare
this PR let the ByteAccumulator recyclable. after invoke ByteAccumulator.transferTo method we can invoke ByteAccumulator.recycle method to reuse byte[] via ByteAccumulator.newByteBuffer method Signed-off-by: Baoyi Chen <[email protected]>
1e39446
to
1f5b446
Compare
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.
This still needs more thought/work.
The bytebuffer pools are really very sensitive as ifa buffer is put in there incorrectly it can have bad security implications, so we need something that is really REALLY certain.
I'm thinking that perhaps we should write a new ByteBufferAccumulator
class from scratch rather than try to make the current one less allocating. We can then come up with a much better API contract to ensure that we don't mess up the pools.
} | ||
|
||
public void copyChunk(ByteBuffer buf) | ||
{ |
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 we need to check that the buf here was the one last returned from newByteBuffer
|
||
if (buf.hasRemaining()) | ||
{ | ||
chunks.add(buf); |
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.
If we always add to the chunks list, then we can end up with a lot of buffers in the list, all max size, but each with just a few bytes in them.
@leonchen83 I will pull in your commits into a new branch and combine it with my efforts on PR #5536. |
@lachlan-roberts |
This work is being continued in PR #5574. |
this PR let the ByteAccumulator recyclable. after invoke ByteAccumulator.transferTo method
we can invoke ByteAccumulator.recycle method to reuse byte[] via ByteAccumulator.newByteArray method
Signed-off-by: Baoyi Chen [email protected]