@InterfaceAudience.Private public class MemStoreLABImpl extends Object implements MemStoreLAB
The MemStoreLAB is basically a bump-the-pointer allocator that allocates big (2MB) byte[] chunks from and then doles it out to threads that request slices into the array.
The purpose of this class is to combat heap fragmentation in the regionserver. By ensuring that all Cells in a given memstore refer only to large chunks of contiguous memory, we ensure that large blocks get freed up when the memstore is flushed.
Without the MSLAB, the byte array allocated during insertion end up interleaved throughout the heap, and the old generation gets progressively more fragmented until a stop-the-world compacting collection occurs.
TODO: we should probably benchmark whether word-aligning the allocations would provide a
performance improvement - probably would speed up the Bytes.toLong/Bytes.toInt calls in KeyValue,
but some of those are cached anyway. The chunks created by this MemStoreLAB can get pooled at
ChunkCreator
. When the Chunk comes from pool, it can be either an on heap or an off heap
backed chunk. The chunks, which this MemStoreLAB creates on its own (when no chunk available from
pool), those will be always on heap backed.
NOTE:if user requested to work with MSLABs (whether on- or off-heap), in
CompactingMemStore
ctor, the CompactingMemStore.indexType
could only be
CompactingMemStore.IndexType.CHUNK_MAP
,that is to say the immutable segments using MSLABs are going to use
CellChunkMap
as their index.
Modifier and Type | Field and Description |
---|---|
private ChunkCreator |
chunkCreator |
(package private) Set<Integer> |
chunks |
private AtomicBoolean |
closed |
private AtomicReference<Chunk> |
currChunk |
private int |
dataChunkSize |
private ReentrantLock |
lock |
(package private) static org.slf4j.Logger |
LOG |
private int |
maxAlloc |
private AtomicBoolean |
reclaimed |
private RefCnt |
refCnt
Its initial value is 1, so it is one bigger than the current count of open scanners which
reading data from this MemStoreLAB.
|
CHUNK_POOL_INITIALSIZE_KEY, CHUNK_POOL_MAXSIZE_KEY, CHUNK_SIZE_DEFAULT, CHUNK_SIZE_KEY, INDEX_CHUNK_SIZE_PERCENTAGE_DEFAULT, INDEX_CHUNK_SIZE_PERCENTAGE_KEY, MAX_ALLOC_DEFAULT, MAX_ALLOC_KEY, MSLAB_CLASS_NAME, POOL_INITIAL_SIZE_DEFAULT, POOL_MAX_SIZE_DEFAULT, USEMSLAB_DEFAULT, USEMSLAB_KEY
Constructor and Description |
---|
MemStoreLABImpl() |
MemStoreLABImpl(org.apache.hadoop.conf.Configuration conf) |
Modifier and Type | Method and Description |
---|---|
void |
close()
Close this instance since it won't be used any more, try to put the chunks back to pool
|
private Cell |
copyBBECellInto(ByteBufferExtendedCell cell,
int maxAlloc)
Mostly a duplicate of
copyCellInto(Cell, int) } done for perf sake. |
private static Cell |
copyBBECToChunkCell(ByteBufferExtendedCell cell,
ByteBuffer buf,
int offset,
int len)
Clone the passed cell by copying its data into the passed buf and create a cell with a chunkid
out of it
|
Cell |
copyCellInto(Cell cell)
Allocates slice in this LAB and copy the passed Cell into this area.
|
private Cell |
copyCellInto(Cell cell,
int maxAlloc) |
private static Cell |
copyToChunkCell(Cell cell,
ByteBuffer buf,
int offset,
int len)
Clone the passed cell by copying its data into the passed buf and create a cell with a chunkid
out of it
|
private static Cell |
createChunkCell(ByteBuffer buf,
int offset,
int len,
int tagsLen,
long sequenceId) |
void |
decScannerCount()
Called when closing a scanner on the data of this MemStoreLAB
|
Cell |
forceCopyOfBigCellInto(Cell cell)
When a cell's size is too big (bigger than maxAlloc), copyCellInto does not allocate it on
MSLAB.
|
(package private) Chunk |
getCurrentChunk() |
Chunk |
getNewExternalChunk(ChunkCreator.ChunkType chunkType) |
Chunk |
getNewExternalChunk(int size) |
(package private) Integer |
getNumOfChunksReturnedToPool(Set<Integer> chunksId) |
private Chunk |
getOrMakeChunk()
Get the current chunk, or, if there is no current chunk, allocate a new one from the JVM.
|
(package private) BlockingQueue<Chunk> |
getPooledChunks() |
(package private) int |
getRefCntValue() |
void |
incScannerCount()
Called when opening a scanner on the data of this MemStoreLAB
|
(package private) boolean |
isClosed() |
boolean |
isOffHeap() |
boolean |
isOnHeap() |
(package private) boolean |
isReclaimed() |
private void |
recycleChunks() |
private void |
tryRetireChunk(Chunk c)
Try to retire the current chunk if it is still
c . |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
isEnabled, newInstance
static final org.slf4j.Logger LOG
private AtomicReference<Chunk> currChunk
private ReentrantLock lock
private final int dataChunkSize
private final int maxAlloc
private final ChunkCreator chunkCreator
private final AtomicBoolean closed
private final AtomicBoolean reclaimed
public MemStoreLABImpl()
public MemStoreLABImpl(org.apache.hadoop.conf.Configuration conf)
public Cell copyCellInto(Cell cell)
MemStoreLAB
copyCellInto
in interface MemStoreLAB
public Cell forceCopyOfBigCellInto(Cell cell)
forceCopyOfBigCellInto
in interface MemStoreLAB
private Cell copyBBECellInto(ByteBufferExtendedCell cell, int maxAlloc)
copyCellInto(Cell, int)
} done for perf sake. It presumes
ByteBufferExtendedCell instead of Cell so we deal with a specific type rather than the super
generic Cell. Removes instanceof checks. Shrinkage is enough to make this inline where before
it was too big. Uses less CPU. See HBASE-20875 for evidence.copyCellInto(Cell, int)
private Cell copyCellInto(Cell cell, int maxAlloc)
private static Cell copyToChunkCell(Cell cell, ByteBuffer buf, int offset, int len)
private static Cell copyBBECToChunkCell(ByteBufferExtendedCell cell, ByteBuffer buf, int offset, int len)
private static Cell createChunkCell(ByteBuffer buf, int offset, int len, int tagsLen, long sequenceId)
public void close()
close
in interface MemStoreLAB
int getRefCntValue()
public void incScannerCount()
incScannerCount
in interface MemStoreLAB
public void decScannerCount()
decScannerCount
in interface MemStoreLAB
private void recycleChunks()
private void tryRetireChunk(Chunk c)
c
. Postcondition is that
curChunk.get() != cc
- the chunk to retireprivate Chunk getOrMakeChunk()
public Chunk getNewExternalChunk(ChunkCreator.ChunkType chunkType)
getNewExternalChunk
in interface MemStoreLAB
public Chunk getNewExternalChunk(int size)
getNewExternalChunk
in interface MemStoreLAB
public boolean isOnHeap()
isOnHeap
in interface MemStoreLAB
public boolean isOffHeap()
isOffHeap
in interface MemStoreLAB
Chunk getCurrentChunk()
BlockingQueue<Chunk> getPooledChunks()
Integer getNumOfChunksReturnedToPool(Set<Integer> chunksId)
boolean isReclaimed()
boolean isClosed()
Copyright © 2007–2020 The Apache Software Foundation. All rights reserved.