diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ImmutableMemStoreLAB.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ImmutableMemStoreLAB.java index 430b642..401c728 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ImmutableMemStoreLAB.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/ImmutableMemStoreLAB.java @@ -37,6 +37,8 @@ public class ImmutableMemStoreLAB implements MemStoreLAB { private final List mslabs; public ImmutableMemStoreLAB(List mslabs) { + assert mslabs != null; + assert mslabs.size() > 0; this.mslabs = mslabs; } @@ -89,4 +91,9 @@ public class ImmutableMemStoreLAB implements MemStoreLAB { checkAndCloseMSLABs(count); } } + + @Override + public boolean isOffheap() { + return mslabs.get(0).isOffheap(); + } } \ No newline at end of file diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java index b7ac212..02b28b8 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreChunkPool.java @@ -262,4 +262,8 @@ public class MemStoreChunkPool implements HeapMemoryTuneObserver { } } } + + public boolean isOffheap() { + return this.offheap; + } } diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreLAB.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreLAB.java index f6d1607..daf95ca 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreLAB.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreLAB.java @@ -83,6 +83,11 @@ public interface MemStoreLAB { */ void decScannerCount(); + /** + * @return Whether off heap based MSLAB in place. + */ + boolean isOffheap(); + public static MemStoreLAB newInstance(Configuration conf) { MemStoreLAB memStoreLAB = null; if (isEnabled(conf)) { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreLABImpl.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreLABImpl.java index 30e4311..6791839 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreLABImpl.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreLABImpl.java @@ -168,6 +168,11 @@ public class MemStoreLABImpl implements MemStoreLAB { } } + @Override + public boolean isOffheap() { + return chunkPool != null && chunkPool.isOffheap(); + } + /** * Try to retire the current chunk if it is still * c. Postcondition is that curChunk.get() diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MutableSegment.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MutableSegment.java index 3dbd7ad..3f4d3e4 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MutableSegment.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MutableSegment.java @@ -86,6 +86,22 @@ public class MutableSegment extends Segment { // removed cell is from MSLAB or not. Will do once HBASE-16438 is in int cellLen = getCellLength(cur); long heapOverheadDelta = heapOverheadChange(cur, true); + // Upserts not using MSLAB at all + // When we work with off heap MSLAB (Kind of off heap memstore) and for addition of this + // Cell, MSLAB is not used, that means we have extra heap space used for this Cell's' + // data. It is not just heap overhead what we have. We have to add the Cell length also + // to the heap overhead part. We have RS level accounting for the cell data and heap + // overhead. When on heap MSLAB in use, we will have checks by adding both these tracked + // sizes to know whether there is any breach in lower/upper global memstore barrier. + // When off heap MSLAB in place, we have 2 checks to know whether we go above off heap + // size barrier(Checking the data size) and/or above the on heap barrier(Checking the + // heap overhead). If we dont add the cell size also into the heap overhead part here, + // we will be doing under tracking of the real heap usage of the memstore and this can + // make global memstore heap space usage to go beyond the water marks and cause GC + // issues or even OOME. + if (this.memStoreLAB != null && this.memStoreLAB.isOffheap()) { + heapOverheadDelta += cellLen; + } this.incSize(-cellLen, -heapOverheadDelta); if (memstoreSize != null) { memstoreSize.decMemstoreSize(cellLen, heapOverheadDelta); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/Segment.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/Segment.java index afdfe6f..683daca 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/Segment.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/Segment.java @@ -56,7 +56,7 @@ public abstract class Segment { private AtomicReference cellSet= new AtomicReference(); private final CellComparator comparator; protected long minSequenceId; - private MemStoreLAB memStoreLAB; + protected MemStoreLAB memStoreLAB; // Sum of sizes of all Cells added to this Segment. Cell's heapSize is considered. This is not // including the heap overhead of this class. protected final AtomicLong dataSize; @@ -277,6 +277,20 @@ public abstract class Segment { cellSize = getCellLength(cellToAdd); } long overhead = heapOverheadChange(cellToAdd, succ); + // When we work with off heap MSLAB (Kind of off heap memstore) and for addition of this Cell, + // MSLAB is not used, that means we have extra heap space used for this Cell's data. It is not + // just heap overhead what we have. We have to add the Cell length also to the heap overhead + // part. We have RS level accounting for the cell data and heap overhead. When on heap MSLAB in + // use, we will have checks by adding both these tracked sizes to know whether there is any + // breach in lower/upper global memstore barrier. When off heap MSLAB in place, we have 2 checks + // to know whether we go above off heap size barrier(Checking the data size) and/or above the on + // heap barrier(Checking the heap overhead). If we dont add the cell size also into the heap + // overhead part here, we will be doing under tracking of the real heap usage of the memstore + // and this can make global memstore heap space usage to go beyond the water marks and cause GC + // issues or even OOME. + if (!mslabUsed && this.memStoreLAB != null && this.memStoreLAB.isOffheap()) { + overhead += cellSize; + } incSize(cellSize, overhead); if (memstoreSize != null) { memstoreSize.incMemstoreSize(cellSize, overhead);