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:
parent
562c2d1074
commit
3bc4d2330a
@ -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()));
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user