commit b436db7d70c8a90b0167dc0e0120f503efb37e3c Author: stack Date: Tue Mar 10 22:16:51 2015 -0700 HBASE-13142 [PERF] Reuse the IPCUtil#buildCellBlock buffer; ADDENDUM diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/ipc/IPCUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/ipc/IPCUtil.java index 414abee..7c6c9ba 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/ipc/IPCUtil.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/ipc/IPCUtil.java @@ -33,6 +33,7 @@ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.CellScanner; import org.apache.hadoop.hbase.HBaseIOException; import org.apache.hadoop.hbase.codec.Codec; +import org.apache.hadoop.hbase.io.BoundedByteBufferPool; import org.apache.hadoop.hbase.io.ByteBufferOutputStream; import org.apache.hadoop.hbase.io.HeapSize; import org.apache.hadoop.hbase.util.Bytes; @@ -101,23 +102,25 @@ public class IPCUtil { * @param codec * @param compressor * @param cellScanner - * @param bb ByteBuffer to use. Can be null. You'd pass in a ByteBuffer if you want to practice - * recycling. If the passed in ByteBuffer is too small, it is discarded and a new one allotted - * so you will get back the passed-in ByteBuffer or a new, right-sized one. SIDE EFFECT!!!!! + * @param pool Pool of ByteBuffers to make use of. Can be null and then we'll allocate + * our own ByteBuffer. * @return Null or byte buffer filled with a cellblock filled with passed-in Cells encoded using * passed in codec and/or compressor; the returned buffer has been - * flipped and is ready for reading. Use limit to find total size. + * flipped and is ready for reading. Use limit to find total size. If pool was not + * null, then this returned ByteBuffer came from there and should be returned to the pool when + * done. * @throws IOException */ @SuppressWarnings("resource") public ByteBuffer buildCellBlock(final Codec codec, final CompressionCodec compressor, - final CellScanner cellScanner, final ByteBuffer bb) + final CellScanner cellScanner, final BoundedByteBufferPool pool) throws IOException { if (cellScanner == null) return null; if (codec == null) throw new CellScannerButNoCodecException(); int bufferSize = this.cellBlockBuildingInitialBufferSize; ByteBufferOutputStream baos = null; - if (bb != null) { + if (pool != null) { + ByteBuffer bb = pool.getBuffer(); bufferSize = bb.capacity(); baos = new ByteBufferOutputStream(bb); } else { diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/ipc/RpcServer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/ipc/RpcServer.java index 89f1be3..9458693 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/ipc/RpcServer.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/ipc/RpcServer.java @@ -393,13 +393,11 @@ public class RpcServer implements RpcServerInterface { // Set the exception as the result of the method invocation. headerBuilder.setException(exceptionBuilder.build()); } - // Get a bb from the reservoir and pass it to buildCellBlock. What comes back will be the - // passed in reservoir bb or a resized one that we should instead add back to the reservoir - // when done. Keep reference so can add it back to the reservoir when finished. This is - // hacky and the hack is not contained but benefits are high when we can avoid a big buffer - // allocation on each rpc. + // Pass reservoir to buildCellBlock. Keep reference to returne so can add it back to the + // reservoir when finished. This is hacky and the hack is not contained but benefits are + // high when we can avoid a big buffer allocation on each rpc. this.cellBlock = ipcUtil.buildCellBlock(this.connection.codec, - this.connection.compressionCodec, cells, reservoir.getBuffer()); + this.connection.compressionCodec, cells, reservoir); if (this.cellBlock != null) { CellBlockMeta.Builder cellBlockBuilder = CellBlockMeta.newBuilder(); // Presumes the cellBlock bytebuffer has been flipped so limit has total size in it.