-
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
Performance of ArrayRetainableByteBufferPool.acquire()
can degenerate pathologically as the buckets grow in size
#9311
Comments
This was found in MultiPartServletTest.testLargePart() when the default buffer pool is used as this test needs 262144 buffers (2GB split in 8KB) to complete. With the
this means it would require 262144! (yes; factorial of 262144, which approaches infinity) @lachlan-roberts could you please add a TODO referring to this issue to your test that uses a non-pooling pool as a workaround? |
The root of this issue seems to be that the algorithm backing There are two major users of the
Maybe we also should expose a constant like |
Signed-off-by: Lachlan Roberts <[email protected]>
Re-instating a It would have the con that it will be either based on Another idea could be to see if using a bitmap would help, see class |
There are 2 reasons for using a Pool:
So for ByteBuffers we don't really want 1. because we don't want to block any allocation in any part of the code. Instead we police maximum memory commitment by other limits (on numbers/sizes). Let's setup a meeting to discuss the options. |
Currently the algorithm in
I think there is scope to add in a queue as a "second level cache":
Using buffers from a queue not only saves on the allocation of the ByteBuffer, but also on the allocation of the retainable wrapper, potentially costing the allocation of the queue structure. So we would configure this pool with:
|
See #9319 for a queued 2nd layer "cache" on the pool. |
See also #9320 that is a After chatting with Simone, I think the key thing to do now is to remove the bucket size from the ByteBufferPool constructor (or at least deprecate that constructor) and work out the pool size vs queue size heuristically. |
I like #9320 better but we should probably benchmark the differences with #9319, possibly both with a micro-benchmark as well as a macro one (our perf test?) as the introduction of I agree that bucket size should be an internal-only concern that we should figure out with a heuristic. It looks like such change to |
@lorban please take over those branches for further work on this. |
…x-documentation-operations-logging * upstream/jetty-12.0.x: (35 commits) Fixes jetty#9326 - Rename DecryptedEndPoint to SslEndPoint. Jetty 10 Upgrade to Hazelcast 5 and totally disable auto join multicast etc.. (fix build on CI) (jetty#9331) jetty#9328 - changes from review jetty#9287 - catch error in ee9 maxRequestSize MultiPart test Jetty 12.0.x 9301 fix ee10 jstl jpms (jetty#9321) Issue jetty#9301 Fix dependencies for ee10-glassfish-jstl module (jetty#9303) Jetty 12 Hazelcast 5.x and disable auto detection/multicast" (jetty#9332) jetty#9287 - fix further test failures Fixed imports. Issue jetty#7650 - Fix race condition when stopping QueuedThreadPool (jetty#9325) jetty#9287 - remove unpaired release of Content.Chunk Issue jetty#8991 - rename websocket isDemanding() method to isAutoDemanding() Issue jetty#9287 - fix failing tests changes f rom review add todo to revert to normal pool after fix for jetty#9311 Issue jetty#9309 - Introducing test for requestlog format with spaces use non-pooling RetainableByteBufferPool to work around performance bug consumeAvailable should use number of reads instead of bytes fix for retainable merge changes from review ...
- fixed double-release bug in MultiPartFormData - used ByteBufferPool.NonPooling pool to work around #9311 Signed-off-by: Ludovic Orban <[email protected]>
- fixed double-release bug in MultiPartFormData - used ByteBufferPool.NonPooling pool to work around #9311 Signed-off-by: Ludovic Orban <[email protected]>
#9408: restored HugeResourceTest: - fixed double-release bug in MultiPartFormData - used ByteBufferPool.NonPooling pool to work around #9311 Signed-off-by: Ludovic Orban <[email protected]>
This adds a QueuedPool that can wrap any other pool and provided a queue of Entries as a kind of cache.
This adds a QueuedPool that can wrap any other pool and provided a queue of Entries as a kind of cache.
Jetty version(s)
12
Description
Since
ArrayRetainableByteBufferPool.acquire()
is backed byConcurrentPool.acquire()
, each execution requires iterating over a number of entries proportional to the usage level of the bucket, i.e.: a bucket that is 90% used requires iterating over 90% of the entries on average.When the number of buffers in a single bucket is quite small (in the 100s), those iterations are so cheap they have a negligible cost as the array is small enough to fit into the CPU cache. But when that number of buffers reaches the 10s of thousands, these iterations become a pathological bottleneck.
The text was updated successfully, but these errors were encountered: