From db2d363db79f2f6c054f0371a202778910d83be8 Mon Sep 17 00:00:00 2001 From: Simone Bordet Date: Thu, 10 Nov 2022 18:06:45 +0100 Subject: [PATCH] Fixes #8810 - ArrayRetainableByteBufferPool inefficiently calculates bucket indices Added constructor that uses IntUnaryOperator to avoid boxing. Deprecated constructor that uses Function. Signed-off-by: Simone Bordet --- .../io/ArrayRetainableByteBufferPool.java | 31 ++++++++++++++++--- .../io/LogarithmicArrayByteBufferPool.java | 7 +++-- .../io/ArrayRetainableByteBufferPoolTest.java | 7 +++-- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ArrayRetainableByteBufferPool.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ArrayRetainableByteBufferPool.java index 94beaccab2f0..c9c6b6d2c1b9 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/ArrayRetainableByteBufferPool.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ArrayRetainableByteBufferPool.java @@ -19,6 +19,7 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.IntUnaryOperator; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.NanoTime; @@ -54,7 +55,7 @@ public class ArrayRetainableByteBufferPool implements RetainableByteBufferPool, private final long _maxDirectMemory; private final AtomicLong _currentHeapMemory = new AtomicLong(); private final AtomicLong _currentDirectMemory = new AtomicLong(); - private final Function _bucketIndexFor; + private final IntUnaryOperator _bucketIndexFor; /** * Creates a new ArrayRetainableByteBufferPool with a default configuration. @@ -91,7 +92,7 @@ public ArrayRetainableByteBufferPool(int minCapacity, int factor, int maxCapacit */ public ArrayRetainableByteBufferPool(int minCapacity, int factor, int maxCapacity, int maxBucketSize, long maxHeapMemory, long maxDirectMemory) { - this(minCapacity, factor, maxCapacity, maxBucketSize, maxHeapMemory, maxDirectMemory, null, null); + this(minCapacity, factor, maxCapacity, maxBucketSize, null, null, maxHeapMemory, maxDirectMemory); } /** @@ -105,9 +106,29 @@ public ArrayRetainableByteBufferPool(int minCapacity, int factor, int maxCapacit * @param maxDirectMemory the max direct memory in bytes, -1 for unlimited memory or 0 to use default heuristic * @param bucketIndexFor a {@link Function} that takes a capacity and returns a bucket index * @param bucketCapacity a {@link Function} that takes a bucket index and returns a capacity + * @deprecated use {@link #ArrayRetainableByteBufferPool(int, int, int, int, IntUnaryOperator, IntUnaryOperator, long, long)} + * instead */ + @Deprecated protected ArrayRetainableByteBufferPool(int minCapacity, int factor, int maxCapacity, int maxBucketSize, long maxHeapMemory, long maxDirectMemory, Function bucketIndexFor, Function bucketCapacity) + { + this(minCapacity, factor, maxCapacity, maxBucketSize, bucketIndexFor::apply, bucketCapacity::apply, maxHeapMemory, maxDirectMemory); + } + + /** + * Creates a new ArrayRetainableByteBufferPool with the given configuration. + * + * @param minCapacity the minimum ByteBuffer capacity + * @param factor the capacity factor + * @param maxCapacity the maximum ByteBuffer capacity + * @param maxBucketSize the maximum number of ByteBuffers for each bucket + * @param bucketIndexFor a {@link IntUnaryOperator} that takes a capacity and returns a bucket index + * @param bucketCapacity a {@link IntUnaryOperator} that takes a bucket index and returns a capacity + * @param maxHeapMemory the max heap memory in bytes, -1 for unlimited memory or 0 to use default heuristic + * @param maxDirectMemory the max direct memory in bytes, -1 for unlimited memory or 0 to use default heuristic + */ + protected ArrayRetainableByteBufferPool(int minCapacity, int factor, int maxCapacity, int maxBucketSize, IntUnaryOperator bucketIndexFor, IntUnaryOperator bucketCapacity, long maxHeapMemory, long maxDirectMemory) { if (minCapacity <= 0) minCapacity = 0; @@ -123,12 +144,12 @@ protected ArrayRetainableByteBufferPool(int minCapacity, int factor, int maxCapa if (bucketCapacity == null) bucketCapacity = i -> (i + 1) * f; - int length = bucketIndexFor.apply(maxCapacity) + 1; + int length = bucketIndexFor.applyAsInt(maxCapacity) + 1; RetainedBucket[] directArray = new RetainedBucket[length]; RetainedBucket[] indirectArray = new RetainedBucket[length]; for (int i = 0; i < directArray.length; i++) { - int capacity = Math.min(bucketCapacity.apply(i), maxCapacity); + int capacity = Math.min(bucketCapacity.applyAsInt(i), maxCapacity); directArray[i] = new RetainedBucket(capacity, maxBucketSize); indirectArray[i] = new RetainedBucket(capacity, maxBucketSize); } @@ -225,7 +246,7 @@ private RetainedBucket bucketFor(int capacity, boolean direct) { if (capacity < _minCapacity) return null; - int idx = _bucketIndexFor.apply(capacity); + int idx = _bucketIndexFor.applyAsInt(capacity); RetainedBucket[] buckets = direct ? _direct : _indirect; if (idx >= buckets.length) return null; diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/LogarithmicArrayByteBufferPool.java b/jetty-io/src/main/java/org/eclipse/jetty/io/LogarithmicArrayByteBufferPool.java index 67da49a2cbec..be2656eb4611 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/LogarithmicArrayByteBufferPool.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/LogarithmicArrayByteBufferPool.java @@ -152,10 +152,11 @@ public LogarithmicRetainablePool(int minCapacity, int maxCapacity, int maxBucket -1, maxCapacity, maxBucketSize, - maxHeapMemory, - maxDirectMemory, c -> 32 - Integer.numberOfLeadingZeros(c - 1), - i -> 1 << i); + i -> 1 << i, + maxHeapMemory, + maxDirectMemory + ); } } } diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/ArrayRetainableByteBufferPoolTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/ArrayRetainableByteBufferPoolTest.java index 637429c6a588..13e0360fb763 100644 --- a/jetty-io/src/test/java/org/eclipse/jetty/io/ArrayRetainableByteBufferPoolTest.java +++ b/jetty-io/src/test/java/org/eclipse/jetty/io/ArrayRetainableByteBufferPoolTest.java @@ -377,10 +377,11 @@ public ExponentialPool(int minCapacity, int maxCapacity, int maxBucketSize, long -1, maxCapacity, maxBucketSize, - maxHeapMemory, - maxDirectMemory, c -> 32 - Integer.numberOfLeadingZeros(c - 1), - i -> 1 << i); + i -> 1 << i, + maxHeapMemory, + maxDirectMemory + ); } }