Fixes #8810 - ArrayRetainableByteBufferPool inefficiently calculates bucket indices (#8882)

Added constructor that uses IntUnaryOperator to avoid boxing.
Deprecated constructor that uses Function<Integer, Integer>.

Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
Simone Bordet 2022-11-10 18:42:53 +01:00 committed by GitHub
parent 34e38d2156
commit 12041da72f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 11 deletions

View File

@ -19,6 +19,7 @@ import java.util.Arrays;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.IntUnaryOperator;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.NanoTime; import org.eclipse.jetty.util.NanoTime;
@ -54,7 +55,7 @@ public class ArrayRetainableByteBufferPool implements RetainableByteBufferPool,
private final long _maxDirectMemory; private final long _maxDirectMemory;
private final AtomicLong _currentHeapMemory = new AtomicLong(); private final AtomicLong _currentHeapMemory = new AtomicLong();
private final AtomicLong _currentDirectMemory = new AtomicLong(); private final AtomicLong _currentDirectMemory = new AtomicLong();
private final Function<Integer, Integer> _bucketIndexFor; private final IntUnaryOperator _bucketIndexFor;
/** /**
* Creates a new ArrayRetainableByteBufferPool with a default configuration. * Creates a new ArrayRetainableByteBufferPool with a default configuration.
@ -91,7 +92,7 @@ public class ArrayRetainableByteBufferPool implements RetainableByteBufferPool,
*/ */
public ArrayRetainableByteBufferPool(int minCapacity, int factor, int maxCapacity, int maxBucketSize, long maxHeapMemory, long maxDirectMemory) 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 class ArrayRetainableByteBufferPool implements RetainableByteBufferPool,
* @param maxDirectMemory the max direct 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
* @param bucketIndexFor a {@link Function} that takes a capacity and returns a bucket index * @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 * @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, protected ArrayRetainableByteBufferPool(int minCapacity, int factor, int maxCapacity, int maxBucketSize, long maxHeapMemory, long maxDirectMemory,
Function<Integer, Integer> bucketIndexFor, Function<Integer, Integer> bucketCapacity) Function<Integer, Integer> bucketIndexFor, Function<Integer, Integer> 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) if (minCapacity <= 0)
minCapacity = 0; minCapacity = 0;
@ -123,12 +144,12 @@ public class ArrayRetainableByteBufferPool implements RetainableByteBufferPool,
if (bucketCapacity == null) if (bucketCapacity == null)
bucketCapacity = i -> (i + 1) * f; bucketCapacity = i -> (i + 1) * f;
int length = bucketIndexFor.apply(maxCapacity) + 1; int length = bucketIndexFor.applyAsInt(maxCapacity) + 1;
RetainedBucket[] directArray = new RetainedBucket[length]; RetainedBucket[] directArray = new RetainedBucket[length];
RetainedBucket[] indirectArray = new RetainedBucket[length]; RetainedBucket[] indirectArray = new RetainedBucket[length];
for (int i = 0; i < directArray.length; i++) 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); directArray[i] = new RetainedBucket(capacity, maxBucketSize);
indirectArray[i] = new RetainedBucket(capacity, maxBucketSize); indirectArray[i] = new RetainedBucket(capacity, maxBucketSize);
} }
@ -225,7 +246,7 @@ public class ArrayRetainableByteBufferPool implements RetainableByteBufferPool,
{ {
if (capacity < _minCapacity) if (capacity < _minCapacity)
return null; return null;
int idx = _bucketIndexFor.apply(capacity); int idx = _bucketIndexFor.applyAsInt(capacity);
RetainedBucket[] buckets = direct ? _direct : _indirect; RetainedBucket[] buckets = direct ? _direct : _indirect;
if (idx >= buckets.length) if (idx >= buckets.length)
return null; return null;

View File

@ -152,10 +152,11 @@ public class LogarithmicArrayByteBufferPool extends ArrayByteBufferPool
-1, -1,
maxCapacity, maxCapacity,
maxBucketSize, maxBucketSize,
maxHeapMemory,
maxDirectMemory,
c -> 32 - Integer.numberOfLeadingZeros(c - 1), c -> 32 - Integer.numberOfLeadingZeros(c - 1),
i -> 1 << i); i -> 1 << i,
maxHeapMemory,
maxDirectMemory
);
} }
} }
} }

View File

@ -377,10 +377,11 @@ public class ArrayRetainableByteBufferPoolTest
-1, -1,
maxCapacity, maxCapacity,
maxBucketSize, maxBucketSize,
maxHeapMemory,
maxDirectMemory,
c -> 32 - Integer.numberOfLeadingZeros(c - 1), c -> 32 - Integer.numberOfLeadingZeros(c - 1),
i -> 1 << i); i -> 1 << i,
maxHeapMemory,
maxDirectMemory
);
} }
} }