Class ByteBuffAllocator
- Direct Known Subclasses:
DeallocateRewriteByteBuffAllocator
ByteBuff
, if we are sure that those ByteBuffers have reached the end of life
cycle, we must do the ByteBuff.release()
to return back the buffers to the pool,
otherwise ByteBuffers leak will happen, and the NIO ByteBuffer pool may be exhausted. there's
possible that the desired memory size is large than ByteBufferPool has, we'll downgrade to
allocate ByteBuffers from heap which meaning the GC pressure may increase again. Of course, an
better way is increasing the ByteBufferPool size if we detected this case. On the other hand, for better memory utilization, we have set an lower bound named minSizeForReservoirUse in this allocator, and if the desired size is less than minSizeForReservoirUse, the allocator will just allocate the ByteBuffer from heap and let the JVM free its memory, because it's too wasting to allocate a single fixed-size ByteBuffer for some small objects.
We recommend to use this class to allocate/free
ByteBuff
in the RPC layer or the entire
read/write path, because it hide the details of memory management and its APIs are more friendly
to the upper layer.-
Nested Class Summary
-
Field Summary
Modifier and TypeFieldDescriptionstatic final String
static final String
private final Queue<ByteBuffer>
protected final int
static final String
Set an alternate bytebuffallocator by setting this config, e.g.static final int
There're some reasons why better to choose 65KB(rather than 64KB) as the default buffer size:static final String
Deprecated.since 2.3.0 and will be removed in 4.0.0.(package private) static final String
Deprecated.since 2.3.0 and will be removed in 4.0.0.(package private) static final String
Deprecated.since 2.3.0 and will be removed in 4.0.0.static final ByteBuffAllocator
private final LongAdder
private long
private long
private static final org.slf4j.Logger
static final String
private final int
private boolean
static final String
private final int
static final ByteBuffAllocator.Recycler
private final LongAdder
protected final boolean
private final AtomicInteger
-
Constructor Summary
ModifierConstructorDescriptionprotected
ByteBuffAllocator
(boolean reservoirEnabled, int maxBufCount, int bufSize, int minSizeForReservoirUse) -
Method Summary
Modifier and TypeMethodDescriptionallocate
(int size) Allocate size bytes from the ByteBufAllocator, Note to call theByteBuff.release()
if no need any more, otherwise the memory leak happen in NIO ByteBuffer pool.Allocate an buffer with buffer size from ByteBuffAllocator, Note to call theByteBuff.release()
if no need any more, otherwise the memory leak happen in NIO ByteBuffer pool.private ByteBuffer
allocateOnHeap
(int size) void
clean()
Free all direct buffers if allocated, mainly used for testing.static ByteBuffAllocator
create
(org.apache.hadoop.conf.Configuration conf, boolean reservoirEnabled) Initialize anByteBuffAllocator
which will try to allocate ByteBuffers from off-heap if reservoir is enabled and the reservoir has enough buffers, otherwise the allocator will just allocate the insufficient buffers from on-heap to meet the requirement.private static ByteBuffAllocator
Initialize anByteBuffAllocator
which only allocate ByteBuffer from on-heap, it's designed for testing purpose or disabled reservoir case.private ByteBuffer
int
int
TheConcurrentLinkedQueue.size()
is O(N) complexity and time-consuming, so DO NOT use the method except in UT.long
static long
getHeapAllocationBytes
(ByteBuffAllocator... allocators) static double
getHeapAllocationRatio
(ByteBuffAllocator... allocators) long
int
int
boolean
protected void
putbackBuffer
(ByteBuffer buf) Return back a ByteBuffer after its use.
-
Field Details
-
LOG
-
HEAP
-
ALLOCATOR_POOL_ENABLED_KEY
- See Also:
-
MAX_BUFFER_COUNT_KEY
- See Also:
-
BUFFER_SIZE_KEY
- See Also:
-
MIN_ALLOCATE_SIZE_KEY
- See Also:
-
BYTEBUFF_ALLOCATOR_CLASS
Set an alternate bytebuffallocator by setting this config, e.g. we can configDeallocateRewriteByteBuffAllocator
to find out prematurely release issues- See Also:
-
DEPRECATED_ALLOCATOR_POOL_ENABLED_KEY
Deprecated.since 2.3.0 and will be removed in 4.0.0. UseALLOCATOR_POOL_ENABLED_KEY
instead.- See Also:
-
DEPRECATED_MAX_BUFFER_COUNT_KEY
Deprecated.since 2.3.0 and will be removed in 4.0.0. UseMAX_BUFFER_COUNT_KEY
instead.- See Also:
-
DEPRECATED_BUFFER_SIZE_KEY
Deprecated.since 2.3.0 and will be removed in 4.0.0. UseBUFFER_SIZE_KEY
instead.- See Also:
-
DEFAULT_BUFFER_SIZE
There're some reasons why better to choose 65KB(rather than 64KB) as the default buffer size:1. Almost all of the data blocks have the block size: 64KB + delta, whose delta is very small, depends on the size of lastKeyValue. If we set buffer.size=64KB, then each block will be allocated as a MultiByteBuff: one 64KB DirectByteBuffer and delta bytes HeapByteBuffer, the HeapByteBuffer will increase the GC pressure. Ideally, we should let the data block to be allocated as a SingleByteBuff, it has simpler data structure, faster access speed, less heap usage.
2. Since the blocks are MultiByteBuff when using buffer.size=64KB, so we have to calculate the checksum by an temp heap copying (see HBASE-21917), while if it's a SingleByteBuff, we can speed the checksum by calling the hadoop' checksum in native lib, which is more faster.
For performance comparison, please see HBASE-22483.
- See Also:
-
NONE
-
reservoirEnabled
-
bufSize
-
maxBufCount
-
usedBufCount
-
maxPoolSizeInfoLevelLogged
-
minSizeForReservoirUse
-
buffers
-
poolAllocationBytes
-
heapAllocationBytes
-
lastPoolAllocationBytes
-
lastHeapAllocationBytes
-
-
Constructor Details
-
ByteBuffAllocator
protected ByteBuffAllocator(boolean reservoirEnabled, int maxBufCount, int bufSize, int minSizeForReservoirUse)
-
-
Method Details
-
create
public static ByteBuffAllocator create(org.apache.hadoop.conf.Configuration conf, boolean reservoirEnabled) Initialize anByteBuffAllocator
which will try to allocate ByteBuffers from off-heap if reservoir is enabled and the reservoir has enough buffers, otherwise the allocator will just allocate the insufficient buffers from on-heap to meet the requirement.- Parameters:
conf
- which get the arguments to initialize the allocator.reservoirEnabled
- indicate whether the reservoir is enabled or disabled. NOTICE: if reservoir is enabled, then we will use the pool allocator to allocate off-heap ByteBuffers and use the HEAP allocator to allocate heap ByteBuffers. Otherwise if reservoir is disabled then all allocations will happen in HEAP instance.- Returns:
- ByteBuffAllocator to manage the byte buffers.
-
createOnHeap
Initialize anByteBuffAllocator
which only allocate ByteBuffer from on-heap, it's designed for testing purpose or disabled reservoir case.- Returns:
- allocator to allocate on-heap ByteBuffer.
-
isReservoirEnabled
-
getHeapAllocationBytes
-
getPoolAllocationBytes
-
getBufferSize
-
getUsedBufferCount
-
getFreeBufferCount
TheConcurrentLinkedQueue.size()
is O(N) complexity and time-consuming, so DO NOT use the method except in UT. -
getTotalBufferCount
-
getHeapAllocationBytes
-
getHeapAllocationRatio
-
allocateOneBuffer
Allocate an buffer with buffer size from ByteBuffAllocator, Note to call theByteBuff.release()
if no need any more, otherwise the memory leak happen in NIO ByteBuffer pool.- Returns:
- an ByteBuff with the buffer size.
-
allocateOnHeap
-
allocate
Allocate size bytes from the ByteBufAllocator, Note to call theByteBuff.release()
if no need any more, otherwise the memory leak happen in NIO ByteBuffer pool.- Parameters:
size
- to allocate- Returns:
- an ByteBuff with the desired size.
-
clean
Free all direct buffers if allocated, mainly used for testing. -
getBuffer
- Returns:
- One free DirectByteBuffer from the pool. If no free ByteBuffer and we have not reached the maximum pool size, it will create a new one and return. In case of max pool size also reached, will return null. When pool returned a ByteBuffer, make sure to return it back to pool after use.
-
putbackBuffer
Return back a ByteBuffer after its use. Don't read/write the ByteBuffer after the returning.- Parameters:
buf
- ByteBuffer to return.
-