@InterfaceAudience.Private public class HeapMemStoreLAB 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 KeyValues 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
Modifier and Type | Class and Description |
---|---|
(package private) static class |
HeapMemStoreLAB.Chunk
A chunk of memory out of which allocations are sliced.
|
Modifier and Type | Field and Description |
---|---|
(package private) static int |
CHUNK_SIZE_DEFAULT |
(package private) static String |
CHUNK_SIZE_KEY |
private MemStoreChunkPool |
chunkPool |
private BlockingQueue<HeapMemStoreLAB.Chunk> |
chunkQueue |
(package private) int |
chunkSize |
private boolean |
closed |
private AtomicReference<HeapMemStoreLAB.Chunk> |
curChunk |
(package private) static org.apache.commons.logging.Log |
LOG |
(package private) static int |
MAX_ALLOC_DEFAULT |
(package private) static String |
MAX_ALLOC_KEY |
(package private) int |
maxAlloc |
private AtomicInteger |
openScannerCount |
private AtomicBoolean |
reclaimed |
Constructor and Description |
---|
HeapMemStoreLAB() |
HeapMemStoreLAB(org.apache.hadoop.conf.Configuration conf) |
Modifier and Type | Method and Description |
---|---|
ByteRange |
allocateBytes(int size)
Allocate a slice of the given length.
|
void |
close()
Close this instance since it won't be used any more, try to put the chunks
back to pool
|
void |
decScannerCount()
Called when closing a scanner on the data of this MemStoreLAB
|
(package private) BlockingQueue<HeapMemStoreLAB.Chunk> |
getChunkQueue() |
(package private) HeapMemStoreLAB.Chunk |
getCurrentChunk() |
private HeapMemStoreLAB.Chunk |
getOrMakeChunk()
Get the current chunk, or, if there is no current chunk,
allocate a new one from the JVM.
|
void |
incScannerCount()
Called when opening a scanner on the data of this MemStoreLAB
|
private void |
tryRetireChunk(HeapMemStoreLAB.Chunk c)
Try to retire the current chunk if it is still
c . |
static final String CHUNK_SIZE_KEY
static final int CHUNK_SIZE_DEFAULT
static final String MAX_ALLOC_KEY
static final int MAX_ALLOC_DEFAULT
static final org.apache.commons.logging.Log LOG
private AtomicReference<HeapMemStoreLAB.Chunk> curChunk
private BlockingQueue<HeapMemStoreLAB.Chunk> chunkQueue
final int chunkSize
final int maxAlloc
private final MemStoreChunkPool chunkPool
private volatile boolean closed
private AtomicBoolean reclaimed
private final AtomicInteger openScannerCount
public HeapMemStoreLAB()
public HeapMemStoreLAB(org.apache.hadoop.conf.Configuration conf)
public ByteRange allocateBytes(int size)
allocateBytes
in interface MemStoreLAB
ByteRange
public void close()
close
in interface MemStoreLAB
public void incScannerCount()
incScannerCount
in interface MemStoreLAB
public void decScannerCount()
decScannerCount
in interface MemStoreLAB
private void tryRetireChunk(HeapMemStoreLAB.Chunk c)
c
. Postcondition is that curChunk.get()
!= cc
- the chunk to retireprivate HeapMemStoreLAB.Chunk getOrMakeChunk()
HeapMemStoreLAB.Chunk getCurrentChunk()
BlockingQueue<HeapMemStoreLAB.Chunk> getChunkQueue()
Copyright © 2007–2019 The Apache Software Foundation. All rights reserved.