Class MemStoreLABImpl
- All Implemented Interfaces:
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.
-
Field Summary
FieldsModifier and TypeFieldDescriptionprivate final ChunkCreatorprivate final AtomicBooleanprivate AtomicReference<Chunk>private final intprivate ReentrantLock(package private) static final org.slf4j.Loggerprivate final intprivate final AtomicBooleanprivate final RefCntIts initial value is 1, so it is one bigger than the current count of open scanners which reading data from this MemStoreLAB.Fields inherited from interface org.apache.hadoop.hbase.regionserver.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 Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidclose()Close this instance since it won't be used any more, try to put the chunks back to poolprivate CellcopyBBECellInto(ByteBufferExtendedCell cell, int maxAlloc) Mostly a duplicate ofcopyCellInto(Cell, int)} done for perf sake.private static CellcopyBBECToChunkCell(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 itcopyCellInto(Cell cell) Allocates slice in this LAB and copy the passed Cell into this area.private CellcopyCellInto(Cell cell, int maxAlloc) private static CellcopyToChunkCell(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 itprivate static CellcreateChunkCell(ByteBuffer buf, int offset, int len, int tagsLen, long sequenceId) voidCalled when closing a scanner on the data of this MemStoreLABforceCopyOfBigCellInto(Cell cell) When a cell's size is too big (bigger than maxAlloc), copyCellInto does not allocate it on MSLAB.(package private) ChunkgetNewExternalChunk(int size) getNewExternalChunk(ChunkCreator.ChunkType chunkType) (package private) IntegergetNumOfChunksReturnedToPool(Set<Integer> chunksId) private ChunkGet the current chunk, or, if there is no current chunk, allocate a new one from the JVM.(package private) BlockingQueue<Chunk>(package private) intvoidCalled when opening a scanner on the data of this MemStoreLAB(package private) booleanisClosed()booleanbooleanisOnHeap()(package private) booleanprivate voidprivate voidTry to retire the current chunk if it is stillc.
-
Field Details
-
LOG
-
currChunk
-
lock
-
chunks
-
dataChunkSize
-
maxAlloc
-
chunkCreator
-
closed
-
reclaimed
-
refCnt
Its initial value is 1, so it is one bigger than the current count of open scanners which reading data from this MemStoreLAB.
-
-
Constructor Details
-
MemStoreLABImpl
public MemStoreLABImpl() -
MemStoreLABImpl
-
-
Method Details
-
copyCellInto
Description copied from interface:MemStoreLABAllocates slice in this LAB and copy the passed Cell into this area. Returns new Cell instance over the copied the data. When this MemStoreLAB can not copy this Cell, it returns null.- Specified by:
copyCellIntoin interfaceMemStoreLAB
-
forceCopyOfBigCellInto
When a cell's size is too big (bigger than maxAlloc), copyCellInto does not allocate it on MSLAB. Since the process of flattening to CellChunkMap assumes that all cells are allocated on MSLAB, during this process, the big cells are copied into MSLAB using this method.- Specified by:
forceCopyOfBigCellIntoin interfaceMemStoreLAB
-
copyBBECellInto
Mostly a duplicate ofcopyCellInto(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.- See Also:
-
copyCellInto
-
copyToChunkCell
Clone the passed cell by copying its data into the passed buf and create a cell with a chunkid out of it -
copyBBECToChunkCell
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 -
createChunkCell
private static Cell createChunkCell(ByteBuffer buf, int offset, int len, int tagsLen, long sequenceId) -
close
Close this instance since it won't be used any more, try to put the chunks back to pool- Specified by:
closein interfaceMemStoreLAB
-
getRefCntValue
int getRefCntValue() -
incScannerCount
Called when opening a scanner on the data of this MemStoreLAB- Specified by:
incScannerCountin interfaceMemStoreLAB
-
decScannerCount
Called when closing a scanner on the data of this MemStoreLAB- Specified by:
decScannerCountin interfaceMemStoreLAB
-
recycleChunks
-
tryRetireChunk
Try to retire the current chunk if it is stillc. Postcondition is that curChunk.get() != c- Parameters:
c- the chunk to retire
-
getOrMakeChunk
Get the current chunk, or, if there is no current chunk, allocate a new one from the JVM. -
getNewExternalChunk
- Specified by:
getNewExternalChunkin interfaceMemStoreLAB
-
getNewExternalChunk
- Specified by:
getNewExternalChunkin interfaceMemStoreLAB
-
isOnHeap
- Specified by:
isOnHeapin interfaceMemStoreLAB
-
isOffHeap
- Specified by:
isOffHeapin interfaceMemStoreLAB
-
getCurrentChunk
-
getPooledChunks
-
getNumOfChunksReturnedToPool
-
isReclaimed
boolean isReclaimed() -
isClosed
boolean isClosed()
-