HBASE-13142 [PERF] Reuse the IPCUtil#buildCellBlock buffer; ADDENDUM

This commit is contained in:
stack 2015-03-10 22:16:51 -07:00
parent d590f87ef4
commit b436db7d70
2 changed files with 13 additions and 12 deletions

View File

@ -33,6 +33,7 @@ import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.CellScanner; import org.apache.hadoop.hbase.CellScanner;
import org.apache.hadoop.hbase.HBaseIOException; import org.apache.hadoop.hbase.HBaseIOException;
import org.apache.hadoop.hbase.codec.Codec; 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.ByteBufferOutputStream;
import org.apache.hadoop.hbase.io.HeapSize; import org.apache.hadoop.hbase.io.HeapSize;
import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Bytes;
@ -101,23 +102,25 @@ public class IPCUtil {
* @param codec * @param codec
* @param compressor * @param compressor
* @param cellScanner * @param cellScanner
* @param bb ByteBuffer to use. Can be null. You'd pass in a ByteBuffer if you want to practice * @param pool Pool of ByteBuffers to make use of. Can be null and then we'll allocate
* recycling. If the passed in ByteBuffer is too small, it is discarded and a new one allotted * our own ByteBuffer.
* so you will get back the passed-in ByteBuffer or a new, right-sized one. SIDE EFFECT!!!!!
* @return Null or byte buffer filled with a cellblock filled with passed-in Cells encoded using * @return Null or byte buffer filled with a cellblock filled with passed-in Cells encoded using
* passed in <code>codec</code> and/or <code>compressor</code>; the returned buffer has been * passed in <code>codec</code> and/or <code>compressor</code>; 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 <code>pool</code> was not
* null, then this returned ByteBuffer came from there and should be returned to the pool when
* done.
* @throws IOException * @throws IOException
*/ */
@SuppressWarnings("resource") @SuppressWarnings("resource")
public ByteBuffer buildCellBlock(final Codec codec, final CompressionCodec compressor, public ByteBuffer buildCellBlock(final Codec codec, final CompressionCodec compressor,
final CellScanner cellScanner, final ByteBuffer bb) final CellScanner cellScanner, final BoundedByteBufferPool pool)
throws IOException { throws IOException {
if (cellScanner == null) return null; if (cellScanner == null) return null;
if (codec == null) throw new CellScannerButNoCodecException(); if (codec == null) throw new CellScannerButNoCodecException();
int bufferSize = this.cellBlockBuildingInitialBufferSize; int bufferSize = this.cellBlockBuildingInitialBufferSize;
ByteBufferOutputStream baos = null; ByteBufferOutputStream baos = null;
if (bb != null) { if (pool != null) {
ByteBuffer bb = pool.getBuffer();
bufferSize = bb.capacity(); bufferSize = bb.capacity();
baos = new ByteBufferOutputStream(bb); baos = new ByteBufferOutputStream(bb);
} else { } else {

View File

@ -393,13 +393,11 @@ public class RpcServer implements RpcServerInterface {
// Set the exception as the result of the method invocation. // Set the exception as the result of the method invocation.
headerBuilder.setException(exceptionBuilder.build()); headerBuilder.setException(exceptionBuilder.build());
} }
// Get a bb from the reservoir and pass it to buildCellBlock. What comes back will be the // Pass reservoir to buildCellBlock. Keep reference to returne so can add it back to the
// passed in reservoir bb or a resized one that we should instead add back to the reservoir // reservoir when finished. This is hacky and the hack is not contained but benefits are
// when done. Keep reference so can add it back to the reservoir when finished. This is // high when we can avoid a big buffer allocation on each rpc.
// 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.cellBlock = ipcUtil.buildCellBlock(this.connection.codec,
this.connection.compressionCodec, cells, reservoir.getBuffer()); this.connection.compressionCodec, cells, reservoir);
if (this.cellBlock != null) { if (this.cellBlock != null) {
CellBlockMeta.Builder cellBlockBuilder = CellBlockMeta.newBuilder(); CellBlockMeta.Builder cellBlockBuilder = CellBlockMeta.newBuilder();
// Presumes the cellBlock bytebuffer has been flipped so limit has total size in it. // Presumes the cellBlock bytebuffer has been flipped so limit has total size in it.