Optimize and minimize bound checks
Motivation: We should minimize and optimize bound checks as much as possible to get the most out of performance. Modifications: - Use bitwise operations to remove branching - Remove branches when possible Result: Better performance for various operations.
This commit is contained in:
parent
4403b1a7ea
commit
af9dc2c6a6
@ -232,11 +232,15 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
|||||||
throw new IllegalArgumentException(String.format(
|
throw new IllegalArgumentException(String.format(
|
||||||
"minWritableBytes: %d (expected: >= 0)", minWritableBytes));
|
"minWritableBytes: %d (expected: >= 0)", minWritableBytes));
|
||||||
}
|
}
|
||||||
|
ensureWritable0(minWritableBytes);
|
||||||
if (minWritableBytes <= writableBytes()) {
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ensureWritable0(int minWritableBytes) {
|
||||||
|
if (minWritableBytes <= writableBytes()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (minWritableBytes > maxCapacity - writerIndex) {
|
if (minWritableBytes > maxCapacity - writerIndex) {
|
||||||
throw new IndexOutOfBoundsException(String.format(
|
throw new IndexOutOfBoundsException(String.format(
|
||||||
"writerIndex(%d) + minWritableBytes(%d) exceeds maxCapacity(%d): %s",
|
"writerIndex(%d) + minWritableBytes(%d) exceeds maxCapacity(%d): %s",
|
||||||
@ -248,7 +252,6 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
|||||||
|
|
||||||
// Adjust to the new capacity.
|
// Adjust to the new capacity.
|
||||||
capacity(newCapacity);
|
capacity(newCapacity);
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -543,21 +546,22 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
|||||||
int nLong = length >>> 3;
|
int nLong = length >>> 3;
|
||||||
int nBytes = length & 7;
|
int nBytes = length & 7;
|
||||||
for (int i = nLong; i > 0; i --) {
|
for (int i = nLong; i > 0; i --) {
|
||||||
setLong(index, 0);
|
_setLong(index, 0);
|
||||||
index += 8;
|
index += 8;
|
||||||
}
|
}
|
||||||
if (nBytes == 4) {
|
if (nBytes == 4) {
|
||||||
setInt(index, 0);
|
_setInt(index, 0);
|
||||||
|
// Not need to update the index as we not will use it after this.
|
||||||
} else if (nBytes < 4) {
|
} else if (nBytes < 4) {
|
||||||
for (int i = nBytes; i > 0; i --) {
|
for (int i = nBytes; i > 0; i --) {
|
||||||
setByte(index, (byte) 0);
|
_setByte(index, (byte) 0);
|
||||||
index ++;
|
index ++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setInt(index, 0);
|
_setInt(index, 0);
|
||||||
index += 4;
|
index += 4;
|
||||||
for (int i = nBytes - 4; i > 0; i --) {
|
for (int i = nBytes - 4; i > 0; i --) {
|
||||||
setByte(index, (byte) 0);
|
_setByte(index, (byte) 0);
|
||||||
index ++;
|
index ++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -566,9 +570,9 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte readByte() {
|
public byte readByte() {
|
||||||
checkReadableBytes(1);
|
checkReadableBytes0(1);
|
||||||
int i = readerIndex;
|
int i = readerIndex;
|
||||||
byte b = getByte(i);
|
byte b = _getByte(i);
|
||||||
readerIndex = i + 1;
|
readerIndex = i + 1;
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
@ -585,7 +589,7 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public short readShort() {
|
public short readShort() {
|
||||||
checkReadableBytes(2);
|
checkReadableBytes0(2);
|
||||||
short v = _getShort(readerIndex);
|
short v = _getShort(readerIndex);
|
||||||
readerIndex += 2;
|
readerIndex += 2;
|
||||||
return v;
|
return v;
|
||||||
@ -607,7 +611,7 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int readUnsignedMedium() {
|
public int readUnsignedMedium() {
|
||||||
checkReadableBytes(3);
|
checkReadableBytes0(3);
|
||||||
int v = _getUnsignedMedium(readerIndex);
|
int v = _getUnsignedMedium(readerIndex);
|
||||||
readerIndex += 3;
|
readerIndex += 3;
|
||||||
return v;
|
return v;
|
||||||
@ -615,7 +619,7 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int readInt() {
|
public int readInt() {
|
||||||
checkReadableBytes(4);
|
checkReadableBytes0(4);
|
||||||
int v = _getInt(readerIndex);
|
int v = _getInt(readerIndex);
|
||||||
readerIndex += 4;
|
readerIndex += 4;
|
||||||
return v;
|
return v;
|
||||||
@ -628,7 +632,7 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long readLong() {
|
public long readLong() {
|
||||||
checkReadableBytes(8);
|
checkReadableBytes0(8);
|
||||||
long v = _getLong(readerIndex);
|
long v = _getLong(readerIndex);
|
||||||
readerIndex += 8;
|
readerIndex += 8;
|
||||||
return v;
|
return v;
|
||||||
@ -751,7 +755,7 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
|||||||
@Override
|
@Override
|
||||||
public ByteBuf writeByte(int value) {
|
public ByteBuf writeByte(int value) {
|
||||||
ensureAccessible();
|
ensureAccessible();
|
||||||
ensureWritable(1);
|
ensureWritable0(1);
|
||||||
_setByte(writerIndex++, value);
|
_setByte(writerIndex++, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -759,7 +763,7 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
|||||||
@Override
|
@Override
|
||||||
public ByteBuf writeShort(int value) {
|
public ByteBuf writeShort(int value) {
|
||||||
ensureAccessible();
|
ensureAccessible();
|
||||||
ensureWritable(2);
|
ensureWritable0(2);
|
||||||
_setShort(writerIndex, value);
|
_setShort(writerIndex, value);
|
||||||
writerIndex += 2;
|
writerIndex += 2;
|
||||||
return this;
|
return this;
|
||||||
@ -768,7 +772,7 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
|||||||
@Override
|
@Override
|
||||||
public ByteBuf writeMedium(int value) {
|
public ByteBuf writeMedium(int value) {
|
||||||
ensureAccessible();
|
ensureAccessible();
|
||||||
ensureWritable(3);
|
ensureWritable0(3);
|
||||||
_setMedium(writerIndex, value);
|
_setMedium(writerIndex, value);
|
||||||
writerIndex += 3;
|
writerIndex += 3;
|
||||||
return this;
|
return this;
|
||||||
@ -777,7 +781,7 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
|||||||
@Override
|
@Override
|
||||||
public ByteBuf writeInt(int value) {
|
public ByteBuf writeInt(int value) {
|
||||||
ensureAccessible();
|
ensureAccessible();
|
||||||
ensureWritable(4);
|
ensureWritable0(4);
|
||||||
_setInt(writerIndex, value);
|
_setInt(writerIndex, value);
|
||||||
writerIndex += 4;
|
writerIndex += 4;
|
||||||
return this;
|
return this;
|
||||||
@ -786,7 +790,7 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
|||||||
@Override
|
@Override
|
||||||
public ByteBuf writeLong(long value) {
|
public ByteBuf writeLong(long value) {
|
||||||
ensureAccessible();
|
ensureAccessible();
|
||||||
ensureWritable(8);
|
ensureWritable0(8);
|
||||||
_setLong(writerIndex, value);
|
_setLong(writerIndex, value);
|
||||||
writerIndex += 8;
|
writerIndex += 8;
|
||||||
return this;
|
return this;
|
||||||
@ -891,25 +895,32 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ensureWritable(length);
|
ensureWritable(length);
|
||||||
checkIndex(writerIndex, length);
|
int wIndex = writerIndex;
|
||||||
|
checkIndex(wIndex, length);
|
||||||
|
|
||||||
int nLong = length >>> 3;
|
int nLong = length >>> 3;
|
||||||
int nBytes = length & 7;
|
int nBytes = length & 7;
|
||||||
for (int i = nLong; i > 0; i --) {
|
for (int i = nLong; i > 0; i --) {
|
||||||
writeLong(0);
|
_setLong(wIndex, 0);
|
||||||
|
wIndex += 8;
|
||||||
}
|
}
|
||||||
if (nBytes == 4) {
|
if (nBytes == 4) {
|
||||||
writeInt(0);
|
_setInt(wIndex, 0);
|
||||||
|
wIndex += 4;
|
||||||
} else if (nBytes < 4) {
|
} else if (nBytes < 4) {
|
||||||
for (int i = nBytes; i > 0; i --) {
|
for (int i = nBytes; i > 0; i --) {
|
||||||
writeByte((byte) 0);
|
_setByte(wIndex, (byte) 0);
|
||||||
|
wIndex++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
writeInt(0);
|
_setInt(wIndex, 0);
|
||||||
|
wIndex += 4;
|
||||||
for (int i = nBytes - 4; i > 0; i --) {
|
for (int i = nBytes - 4; i > 0; i --) {
|
||||||
writeByte((byte) 0);
|
_setByte(wIndex, (byte) 0);
|
||||||
|
wIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
writerIndex = wIndex;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1117,19 +1128,12 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected final void checkIndex(int index) {
|
protected final void checkIndex(int index) {
|
||||||
ensureAccessible();
|
checkIndex(index, 1);
|
||||||
if (index < 0 || index >= capacity()) {
|
|
||||||
throw new IndexOutOfBoundsException(String.format(
|
|
||||||
"index: %d (expected: range(0, %d))", index, capacity()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void checkIndex(int index, int fieldLength) {
|
protected final void checkIndex(int index, int fieldLength) {
|
||||||
ensureAccessible();
|
ensureAccessible();
|
||||||
if (fieldLength < 0) {
|
if (isInvalid(index, fieldLength, capacity())) {
|
||||||
throw new IllegalArgumentException("length: " + fieldLength + " (expected: >= 0)");
|
|
||||||
}
|
|
||||||
if (index < 0 || index > capacity() - fieldLength) {
|
|
||||||
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()));
|
||||||
}
|
}
|
||||||
@ -1137,7 +1141,7 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
|||||||
|
|
||||||
protected final void checkSrcIndex(int index, int length, int srcIndex, int srcCapacity) {
|
protected final void checkSrcIndex(int index, int length, int srcIndex, int srcCapacity) {
|
||||||
checkIndex(index, length);
|
checkIndex(index, length);
|
||||||
if (srcIndex < 0 || srcIndex > srcCapacity - length) {
|
if (isInvalid(srcIndex, length, srcCapacity)) {
|
||||||
throw new IndexOutOfBoundsException(String.format(
|
throw new IndexOutOfBoundsException(String.format(
|
||||||
"srcIndex: %d, length: %d (expected: range(0, %d))", srcIndex, length, srcCapacity));
|
"srcIndex: %d, length: %d (expected: range(0, %d))", srcIndex, length, srcCapacity));
|
||||||
}
|
}
|
||||||
@ -1145,22 +1149,30 @@ public abstract class AbstractByteBuf extends ByteBuf {
|
|||||||
|
|
||||||
protected final void checkDstIndex(int index, int length, int dstIndex, int dstCapacity) {
|
protected final void checkDstIndex(int index, int length, int dstIndex, int dstCapacity) {
|
||||||
checkIndex(index, length);
|
checkIndex(index, length);
|
||||||
if (dstIndex < 0 || dstIndex > dstCapacity - length) {
|
if (isInvalid(dstIndex, length, dstCapacity)) {
|
||||||
throw new IndexOutOfBoundsException(String.format(
|
throw new IndexOutOfBoundsException(String.format(
|
||||||
"dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dstCapacity));
|
"dstIndex: %d, length: %d (expected: range(0, %d))", dstIndex, length, dstCapacity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isInvalid(int index, int length, int capacity) {
|
||||||
|
return (index | length | (index + length) | (capacity - (index + length))) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throws an {@link IndexOutOfBoundsException} if the current
|
* Throws an {@link IndexOutOfBoundsException} if the current
|
||||||
* {@linkplain #readableBytes() readable bytes} of this buffer is less
|
* {@linkplain #readableBytes() readable bytes} of this buffer is less
|
||||||
* than the specified value.
|
* than the specified value.
|
||||||
*/
|
*/
|
||||||
protected final void checkReadableBytes(int minimumReadableBytes) {
|
protected final void checkReadableBytes(int minimumReadableBytes) {
|
||||||
ensureAccessible();
|
|
||||||
if (minimumReadableBytes < 0) {
|
if (minimumReadableBytes < 0) {
|
||||||
throw new IllegalArgumentException("minimumReadableBytes: " + minimumReadableBytes + " (expected: >= 0)");
|
throw new IllegalArgumentException("minimumReadableBytes: " + minimumReadableBytes + " (expected: >= 0)");
|
||||||
}
|
}
|
||||||
|
checkReadableBytes0(minimumReadableBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkReadableBytes0(int minimumReadableBytes) {
|
||||||
|
ensureAccessible();
|
||||||
if (readerIndex > writerIndex - minimumReadableBytes) {
|
if (readerIndex > writerIndex - minimumReadableBytes) {
|
||||||
throw new IndexOutOfBoundsException(String.format(
|
throw new IndexOutOfBoundsException(String.format(
|
||||||
"readerIndex(%d) + length(%d) exceeds writerIndex(%d): %s",
|
"readerIndex(%d) + length(%d) exceeds writerIndex(%d): %s",
|
||||||
|
Loading…
Reference in New Issue
Block a user