Minimize reference count checks in SlicedByteBuf

Motivation:

SlicedByteBuf did double reference count checking for various bulk operations, which affects performance.

Modifications:

- Add package private method to AbstractByteBuf that can be used to check indexes without check the reference count
- Use this new method in the bulk operation os SlicedByteBuf as the reference count checks take place on the wrapped buffer anyway
- Fix test-case to not try to read data that is out of the bounds of the buffer.

Result:

Better performance on bulk operations when using SlicedByteBuf (and sub-classes)
This commit is contained in:
Norman Maurer 2015-10-16 13:20:51 +02:00
parent 562c2d1074
commit 3bc4d2330a
3 changed files with 21 additions and 16 deletions

View File

@ -1133,6 +1133,10 @@ public abstract class AbstractByteBuf extends ByteBuf {
protected final void checkIndex(int index, int fieldLength) { protected final void checkIndex(int index, int fieldLength) {
ensureAccessible(); ensureAccessible();
checkIndex0(index, fieldLength);
}
final void checkIndex0(int index, int fieldLength) {
if (isInvalid(index, fieldLength, capacity())) { if (isInvalid(index, fieldLength, capacity())) {
throw new IndexOutOfBoundsException(String.format( throw new IndexOutOfBoundsException(String.format(
"index: %d, length: %d (expected: range(0, %d))", index, fieldLength, capacity())); "index: %d, length: %d (expected: range(0, %d))", index, fieldLength, capacity()));

View File

@ -146,33 +146,33 @@ public class SlicedByteBuf extends AbstractDerivedByteBuf {
@Override @Override
public ByteBuf copy(int index, int length) { public ByteBuf copy(int index, int length) {
checkIndex(index, length); checkIndex0(index, length);
return buffer.copy(idx(index), length); return buffer.copy(idx(index), length);
} }
@Override @Override
public ByteBuf slice(int index, int length) { public ByteBuf slice(int index, int length) {
checkIndex(index, length); checkIndex0(index, length);
return buffer.slice(idx(index), length); return buffer.slice(idx(index), length);
} }
@Override @Override
public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) { public ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length) {
checkIndex(index, length); checkIndex0(index, length);
buffer.getBytes(idx(index), dst, dstIndex, length); buffer.getBytes(idx(index), dst, dstIndex, length);
return this; return this;
} }
@Override @Override
public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) { public ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length) {
checkIndex(index, length); checkIndex0(index, length);
buffer.getBytes(idx(index), dst, dstIndex, length); buffer.getBytes(idx(index), dst, dstIndex, length);
return this; return this;
} }
@Override @Override
public ByteBuf getBytes(int index, ByteBuffer dst) { public ByteBuf getBytes(int index, ByteBuffer dst) {
checkIndex(index, dst.remaining()); checkIndex0(index, dst.remaining());
buffer.getBytes(idx(index), dst); buffer.getBytes(idx(index), dst);
return this; return this;
} }
@ -204,47 +204,47 @@ public class SlicedByteBuf extends AbstractDerivedByteBuf {
@Override @Override
public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) { public ByteBuf setBytes(int index, byte[] src, int srcIndex, int length) {
checkIndex(index, length); checkIndex0(index, length);
buffer.setBytes(idx(index), src, srcIndex, length); buffer.setBytes(idx(index), src, srcIndex, length);
return this; return this;
} }
@Override @Override
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) { public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
checkIndex(index, length); checkIndex0(index, length);
buffer.setBytes(idx(index), src, srcIndex, length); buffer.setBytes(idx(index), src, srcIndex, length);
return this; return this;
} }
@Override @Override
public ByteBuf setBytes(int index, ByteBuffer src) { public ByteBuf setBytes(int index, ByteBuffer src) {
checkIndex(index, src.remaining()); checkIndex0(index, src.remaining());
buffer.setBytes(idx(index), src); buffer.setBytes(idx(index), src);
return this; return this;
} }
@Override @Override
public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException { public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
checkIndex(index, length); checkIndex0(index, length);
buffer.getBytes(idx(index), out, length); buffer.getBytes(idx(index), out, length);
return this; return this;
} }
@Override @Override
public int getBytes(int index, GatheringByteChannel out, int length) throws IOException { public int getBytes(int index, GatheringByteChannel out, int length) throws IOException {
checkIndex(index, length); checkIndex0(index, length);
return buffer.getBytes(idx(index), out, length); return buffer.getBytes(idx(index), out, length);
} }
@Override @Override
public int setBytes(int index, InputStream in, int length) throws IOException { public int setBytes(int index, InputStream in, int length) throws IOException {
checkIndex(index, length); checkIndex0(index, length);
return buffer.setBytes(idx(index), in, length); return buffer.setBytes(idx(index), in, length);
} }
@Override @Override
public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
checkIndex(index, length); checkIndex0(index, length);
return buffer.setBytes(idx(index), in, length); return buffer.setBytes(idx(index), in, length);
} }
@ -255,24 +255,24 @@ public class SlicedByteBuf extends AbstractDerivedByteBuf {
@Override @Override
public ByteBuffer nioBuffer(int index, int length) { public ByteBuffer nioBuffer(int index, int length) {
checkIndex(index, length); checkIndex0(index, length);
return buffer.nioBuffer(idx(index), length); return buffer.nioBuffer(idx(index), length);
} }
@Override @Override
public ByteBuffer[] nioBuffers(int index, int length) { public ByteBuffer[] nioBuffers(int index, int length) {
checkIndex(index, length); checkIndex0(index, length);
return buffer.nioBuffers(idx(index), length); return buffer.nioBuffers(idx(index), length);
} }
@Override @Override
public ByteBuffer internalNioBuffer(int index, int length) { public ByteBuffer internalNioBuffer(int index, int length) {
checkIndex(index, length);
return nioBuffer(index, length); return nioBuffer(index, length);
} }
@Override @Override
public int forEachByte(int index, int length, ByteBufProcessor processor) { public int forEachByte(int index, int length, ByteBufProcessor processor) {
checkIndex0(index, length);
int ret = buffer.forEachByte(idx(index), length, processor); int ret = buffer.forEachByte(idx(index), length, processor);
if (ret >= adjustment) { if (ret >= adjustment) {
return ret - adjustment; return ret - adjustment;
@ -283,6 +283,7 @@ public class SlicedByteBuf extends AbstractDerivedByteBuf {
@Override @Override
public int forEachByteDesc(int index, int length, ByteBufProcessor processor) { public int forEachByteDesc(int index, int length, ByteBufProcessor processor) {
checkIndex0(index, length);
int ret = buffer.forEachByteDesc(idx(index), length, processor); int ret = buffer.forEachByteDesc(idx(index), length, processor);
if (ret >= adjustment) { if (ret >= adjustment) {
return ret - adjustment; return ret - adjustment;

View File

@ -2041,7 +2041,7 @@ public abstract class AbstractByteBufTest {
@Test(expected = IllegalReferenceCountException.class) @Test(expected = IllegalReferenceCountException.class)
public void testGetBytesAfterRelease() { public void testGetBytesAfterRelease() {
releasedBuffer().getBytes(0, releaseLater(buffer())); releasedBuffer().getBytes(0, releaseLater(buffer(8)));
} }
@Test(expected = IllegalReferenceCountException.class) @Test(expected = IllegalReferenceCountException.class)