Class AdaptivePoolingAllocator
- All Implemented Interfaces:
AdaptiveByteBufAllocator.AdaptiveAllocatorApi
The allocator is organized into a list of Magazines, and each magazine has a chunk-buffer that they allocate buffers from.
The magazines hold the mutexes that ensure the thread-safety of the allocator, and each thread picks a magazine based on the id of the thread. This spreads the contention of multi-threaded access across the magazines. If contention is detected above a certain threshold, the number of magazines are increased in response to the contention.
The magazines maintain histograms of the sizes of the allocations they do. The histograms are used to compute the preferred chunk size. The preferred chunk size is one that is big enough to service 10 allocations of the 99-percentile size. This way, the chunk size is adapted to the allocation patterns.
Computing the preferred chunk size is a somewhat expensive operation. Therefore, the frequency with which this is done, is also adapted to the allocation pattern. If a newly computed preferred chunk is the same as the previous preferred chunk size, then the frequency is reduced. Otherwise, the frequency is increased.
This allows the allocator to quickly respond to changes in the application workload, without suffering undue overhead from maintaining its statistics.
Since magazines are "relatively thread-local", the allocator has a central queue that allow excess chunks from any
magazine, to be shared with other magazines.
The createSharedChunkQueue()
method can be overridden to customize this queue.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescription(package private) static final class
private static class
private static final class
(package private) static interface
The strategy for howAdaptivePoolingAllocator
should allocate chunk buffers.private static final class
(package private) static enum
-
Field Summary
FieldsModifier and TypeFieldDescriptionprivate static final int
private static final int
The capacity if the central queue that allow chunks to be shared across magazines.private final Queue
<AdaptivePoolingAllocator.Chunk> private final AdaptivePoolingAllocator.ChunkAllocator
private static final int
private boolean
private static final int
private final Set
<AdaptivePoolingAllocator.Magazine> private static final int
The capacity if the magazine local buffer queue.private final StampedLock
private AdaptivePoolingAllocator.Magazine[]
private static final int
The maximum size of a pooled chunk, in bytes.private static final int
private static final int
private static final Object
private static final int
private final FastThreadLocal
<Object> -
Constructor Summary
ConstructorsConstructorDescriptionAdaptivePoolingAllocator
(AdaptivePoolingAllocator.ChunkAllocator chunkAllocator, AdaptivePoolingAllocator.MagazineCaching magazineCaching) -
Method Summary
Modifier and TypeMethodDescriptionallocate
(int size, int maxCapacity) (package private) void
allocate
(int size, int maxCapacity, AdaptivePoolingAllocator.AdaptiveByteBuf into) Allocate into the given buffer.allocate
(int size, int maxCapacity, Thread currentThread, AdaptivePoolingAllocator.AdaptiveByteBuf buf) allocateFallback
(int size, int maxCapacity, Thread currentThread, AdaptivePoolingAllocator.AdaptiveByteBuf buf) private static Queue
<AdaptivePoolingAllocator.Chunk> Create a thread-safe multi-producer, multi-consumer queue to hold chunks that spill over from the internal Magazines.protected void
finalize()
private void
free()
getFallbackMagazine
(Thread currentThread) private boolean
(package private) static int
sizeBucket
(int size) private boolean
tryExpandMagazines
(int currentLength) long
-
Field Details
-
EXPANSION_ATTEMPTS
private static final int EXPANSION_ATTEMPTS- See Also:
-
INITIAL_MAGAZINES
private static final int INITIAL_MAGAZINES- See Also:
-
RETIRE_CAPACITY
private static final int RETIRE_CAPACITY- See Also:
-
MIN_CHUNK_SIZE
private static final int MIN_CHUNK_SIZE- See Also:
-
MAX_STRIPES
private static final int MAX_STRIPES -
BUFS_PER_CHUNK
private static final int BUFS_PER_CHUNK- See Also:
-
MAX_CHUNK_SIZE
private static final int MAX_CHUNK_SIZEThe maximum size of a pooled chunk, in bytes. Allocations bigger than this will never be pooled.This number is 10 MiB, and is derived from the limitations of internal histograms.
- See Also:
-
CENTRAL_QUEUE_CAPACITY
private static final int CENTRAL_QUEUE_CAPACITYThe capacity if the central queue that allow chunks to be shared across magazines. The default size isNettyRuntime.availableProcessors()
, and the maximum number of magazines is twice this.This means the maximum amount of memory that we can have allocated-but-not-in-use is 5 *
NettyRuntime.availableProcessors()
*MAX_CHUNK_SIZE
bytes. -
MAGAZINE_BUFFER_QUEUE_CAPACITY
private static final int MAGAZINE_BUFFER_QUEUE_CAPACITYThe capacity if the magazine local buffer queue. This queue just pools the outer ByteBuf instance and not the actual memory and so helps to reduce GC pressure. -
NO_MAGAZINE
-
chunkAllocator
-
centralQueue
-
magazineExpandLock
-
magazines
-
threadLocalMagazine
-
liveCachedMagazines
-
freed
private volatile boolean freed
-
-
Constructor Details
-
AdaptivePoolingAllocator
AdaptivePoolingAllocator(AdaptivePoolingAllocator.ChunkAllocator chunkAllocator, AdaptivePoolingAllocator.MagazineCaching magazineCaching)
-
-
Method Details
-
allocate
- Specified by:
allocate
in interfaceAdaptiveByteBufAllocator.AdaptiveAllocatorApi
-
allocate
private AdaptivePoolingAllocator.AdaptiveByteBuf allocate(int size, int maxCapacity, Thread currentThread, AdaptivePoolingAllocator.AdaptiveByteBuf buf) -
allocateFallback
private AdaptivePoolingAllocator.AdaptiveByteBuf allocateFallback(int size, int maxCapacity, Thread currentThread, AdaptivePoolingAllocator.AdaptiveByteBuf buf) -
getFallbackMagazine
-
allocate
Allocate into the given buffer. Used byAdaptivePoolingAllocator.AdaptiveByteBuf.capacity(int)
. -
usedMemory
public long usedMemory()- Specified by:
usedMemory
in interfaceAdaptiveByteBufAllocator.AdaptiveAllocatorApi
-
tryExpandMagazines
private boolean tryExpandMagazines(int currentLength) -
offerToQueue
-
finalize
-
free
private void free() -
sizeBucket
static int sizeBucket(int size)