You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by md...@apache.org on 2018/07/20 19:51:10 UTC
[18/29] hbase git commit: HBASE-20875 MemStoreLABImp::copyIntoCell
uses 7% CPU when writing
HBASE-20875 MemStoreLABImp::copyIntoCell uses 7% CPU when writing
Make the #copyCellInto method smaller so it inlines; we do it by
checking for the common type early and then taking a code path
that presumes ByteBufferExtendedCell -- avoids checks.
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/2bf5e46a
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/2bf5e46a
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/2bf5e46a
Branch: refs/heads/HBASE-20749
Commit: 2bf5e46a33af9724f4db0376a70a217b5071fc6f
Parents: 8c85763
Author: Michael Stack <st...@apache.org>
Authored: Wed Jul 11 22:40:04 2018 -0400
Committer: Michael Stack <st...@apache.org>
Committed: Wed Jul 18 20:41:19 2018 -0700
----------------------------------------------------------------------
.../hbase/regionserver/MemStoreLABImpl.java | 69 +++++++++++++++++++-
1 file changed, 66 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hbase/blob/2bf5e46a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/MemStoreLABImpl.java
----------------------------------------------------------------------
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 ce775f8..6f1ee92 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
@@ -29,6 +29,7 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.ByteBufferExtendedCell;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.ExtendedCell;
import org.apache.hadoop.hbase.KeyValueUtil;
@@ -108,7 +109,10 @@ public class MemStoreLABImpl implements MemStoreLAB {
@Override
public Cell copyCellInto(Cell cell) {
- return copyCellInto(cell, maxAlloc);
+ // See head of copyBBECellInto for how it differs from copyCellInto
+ return (cell instanceof ByteBufferExtendedCell)?
+ copyBBECellInto((ByteBufferExtendedCell)cell, maxAlloc):
+ copyCellInto(cell, maxAlloc);
}
/**
@@ -133,6 +137,47 @@ public class MemStoreLABImpl implements MemStoreLAB {
}
}
+ /**
+ * Mostly a duplicate of {@link #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.
+ * @see #copyCellInto(Cell, int)
+ */
+ private Cell copyBBECellInto(ByteBufferExtendedCell cell, int maxAlloc) {
+ int size = cell.getSerializedSize();
+ Preconditions.checkArgument(size >= 0, "negative size");
+ // Callers should satisfy large allocations from JVM heap so limit fragmentation.
+ if (size > maxAlloc) {
+ return null;
+ }
+ Chunk c = null;
+ int allocOffset = 0;
+ while (true) {
+ // Try to get the chunk
+ c = getOrMakeChunk();
+ // We may get null because the some other thread succeeded in getting the lock
+ // and so the current thread has to try again to make its chunk or grab the chunk
+ // that the other thread created
+ // Try to allocate from this chunk
+ if (c != null) {
+ allocOffset = c.alloc(size);
+ if (allocOffset != -1) {
+ // We succeeded - this is the common case - small alloc
+ // from a big buffer
+ break;
+ }
+ // not enough space!
+ // try to retire this chunk
+ tryRetireChunk(c);
+ }
+ }
+ return copyBBECToChunkCell(cell, c.getData(), allocOffset, size);
+ }
+
+ /**
+ * @see #copyBBECellInto(ByteBufferExtendedCell, int)
+ */
private Cell copyCellInto(Cell cell, int maxAlloc) {
int size = Segment.getCellLength(cell);
Preconditions.checkArgument(size >= 0, "negative size");
@@ -168,6 +213,7 @@ public class MemStoreLABImpl implements MemStoreLAB {
/**
* Clone the passed cell by copying its data into the passed buf and create a cell with a chunkid
* out of it
+ * @see #copyBBECToChunkCell(ByteBufferExtendedCell, ByteBuffer, int, int)
*/
private static Cell copyToChunkCell(Cell cell, ByteBuffer buf, int offset, int len) {
int tagsLen = cell.getTagsLength();
@@ -179,6 +225,23 @@ public class MemStoreLABImpl implements MemStoreLAB {
// serialization format only.
KeyValueUtil.appendTo(cell, buf, offset, true);
}
+ return createChunkCell(buf, offset, len, tagsLen, cell.getSequenceId());
+ }
+
+ /**
+ * Clone the passed cell by copying its data into the passed buf and create a cell with a chunkid
+ * out of it
+ * @see #copyToChunkCell(Cell, ByteBuffer, int, int)
+ */
+ private static Cell copyBBECToChunkCell(ByteBufferExtendedCell cell, ByteBuffer buf, int offset,
+ int len) {
+ int tagsLen = cell.getTagsLength();
+ cell.write(buf, offset);
+ return createChunkCell(buf, offset, len, tagsLen, cell.getSequenceId());
+ }
+
+ private static Cell createChunkCell(ByteBuffer buf, int offset, int len, int tagsLen,
+ long sequenceId) {
// TODO : write the seqid here. For writing seqId we should create a new cell type so
// that seqId is not used as the state
if (tagsLen == 0) {
@@ -186,9 +249,9 @@ public class MemStoreLABImpl implements MemStoreLAB {
// which directly return tagsLen as 0. So we avoid parsing many length components in
// reading the tagLength stored in the backing buffer. The Memstore addition of every Cell
// call getTagsLength().
- return new NoTagByteBufferChunkKeyValue(buf, offset, len, cell.getSequenceId());
+ return new NoTagByteBufferChunkKeyValue(buf, offset, len, sequenceId);
} else {
- return new ByteBufferChunkKeyValue(buf, offset, len, cell.getSequenceId());
+ return new ByteBufferChunkKeyValue(buf, offset, len, sequenceId);
}
}