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) {
ensureAccessible();
checkIndex0(index, fieldLength);
}
final void checkIndex0(int index, int fieldLength) {
if (isInvalid(index, fieldLength, capacity())) {
throw new IndexOutOfBoundsException(String.format(
"index: %d, length: %d (expected: range(0, %d))", index, fieldLength, capacity()));

View File

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

View File

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