From ffe7aafd8252a382aa0a651d3e9fb84065304da6 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Fri, 9 Oct 2015 23:28:14 +0200 Subject: [PATCH] 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. --- .../java/io/netty/buffer/AbstractByteBuf.java | 84 +++++++++++-------- 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java b/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java index 2fab7b8a39..6e6ccabc91 100644 --- a/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java +++ b/buffer/src/main/java/io/netty/buffer/AbstractByteBuf.java @@ -233,9 +233,13 @@ public abstract class AbstractByteBuf extends ByteBuf { throw new IllegalArgumentException(String.format( "minWritableBytes: %d (expected: >= 0)", minWritableBytes)); } + ensureWritable0(minWritableBytes); + return this; + } + private void ensureWritable0(int minWritableBytes) { if (minWritableBytes <= writableBytes()) { - return this; + return; } if (minWritableBytes > maxCapacity - writerIndex) { @@ -249,7 +253,6 @@ public abstract class AbstractByteBuf extends ByteBuf { // Adjust to the new capacity. capacity(newCapacity); - return this; } @Override @@ -516,21 +519,22 @@ public abstract class AbstractByteBuf extends ByteBuf { int nLong = length >>> 3; int nBytes = length & 7; for (int i = nLong; i > 0; i --) { - setLong(index, 0); + _setLong(index, 0); index += 8; } 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) { for (int i = nBytes; i > 0; i --) { - setByte(index, (byte) 0); + _setByte(index, (byte) 0); index ++; } } else { - setInt(index, 0); + _setInt(index, 0); index += 4; for (int i = nBytes - 4; i > 0; i --) { - setByte(index, (byte) 0); + _setByte(index, (byte) 0); index ++; } } @@ -539,9 +543,9 @@ public abstract class AbstractByteBuf extends ByteBuf { @Override public byte readByte() { - checkReadableBytes(1); + checkReadableBytes0(1); int i = readerIndex; - byte b = getByte(i); + byte b = _getByte(i); readerIndex = i + 1; return b; } @@ -558,7 +562,7 @@ public abstract class AbstractByteBuf extends ByteBuf { @Override public short readShort() { - checkReadableBytes(2); + checkReadableBytes0(2); short v = _getShort(readerIndex); readerIndex += 2; return v; @@ -580,7 +584,7 @@ public abstract class AbstractByteBuf extends ByteBuf { @Override public int readUnsignedMedium() { - checkReadableBytes(3); + checkReadableBytes0(3); int v = _getUnsignedMedium(readerIndex); readerIndex += 3; return v; @@ -588,7 +592,7 @@ public abstract class AbstractByteBuf extends ByteBuf { @Override public int readInt() { - checkReadableBytes(4); + checkReadableBytes0(4); int v = _getInt(readerIndex); readerIndex += 4; return v; @@ -601,7 +605,7 @@ public abstract class AbstractByteBuf extends ByteBuf { @Override public long readLong() { - checkReadableBytes(8); + checkReadableBytes0(8); long v = _getLong(readerIndex); readerIndex += 8; return v; @@ -724,7 +728,7 @@ public abstract class AbstractByteBuf extends ByteBuf { @Override public ByteBuf writeByte(int value) { ensureAccessible(); - ensureWritable(1); + ensureWritable0(1); _setByte(writerIndex++, value); return this; } @@ -732,7 +736,7 @@ public abstract class AbstractByteBuf extends ByteBuf { @Override public ByteBuf writeShort(int value) { ensureAccessible(); - ensureWritable(2); + ensureWritable0(2); _setShort(writerIndex, value); writerIndex += 2; return this; @@ -741,7 +745,7 @@ public abstract class AbstractByteBuf extends ByteBuf { @Override public ByteBuf writeMedium(int value) { ensureAccessible(); - ensureWritable(3); + ensureWritable0(3); _setMedium(writerIndex, value); writerIndex += 3; return this; @@ -750,7 +754,7 @@ public abstract class AbstractByteBuf extends ByteBuf { @Override public ByteBuf writeInt(int value) { ensureAccessible(); - ensureWritable(4); + ensureWritable0(4); _setInt(writerIndex, value); writerIndex += 4; return this; @@ -759,7 +763,7 @@ public abstract class AbstractByteBuf extends ByteBuf { @Override public ByteBuf writeLong(long value) { ensureAccessible(); - ensureWritable(8); + ensureWritable0(8); _setLong(writerIndex, value); writerIndex += 8; return this; @@ -864,25 +868,32 @@ public abstract class AbstractByteBuf extends ByteBuf { } ensureWritable(length); - checkIndex(writerIndex, length); + int wIndex = writerIndex; + checkIndex(wIndex, length); int nLong = length >>> 3; int nBytes = length & 7; for (int i = nLong; i > 0; i --) { - writeLong(0); + _setLong(wIndex, 0); + wIndex += 8; } if (nBytes == 4) { - writeInt(0); + _setInt(wIndex, 0); + wIndex += 4; } else if (nBytes < 4) { for (int i = nBytes; i > 0; i --) { - writeByte((byte) 0); + _setByte(wIndex, (byte) 0); + wIndex++; } } else { - writeInt(0); + _setInt(wIndex, 0); + wIndex += 4; for (int i = nBytes - 4; i > 0; i --) { - writeByte((byte) 0); + _setByte(wIndex, (byte) 0); + wIndex++; } } + writerIndex = wIndex; return this; } @@ -1090,19 +1101,12 @@ public abstract class AbstractByteBuf extends ByteBuf { } protected final void checkIndex(int index) { - ensureAccessible(); - if (index < 0 || index >= capacity()) { - throw new IndexOutOfBoundsException(String.format( - "index: %d (expected: range(0, %d))", index, capacity())); - } + checkIndex(index, 1); } protected final void checkIndex(int index, int fieldLength) { ensureAccessible(); - if (fieldLength < 0) { - throw new IllegalArgumentException("length: " + fieldLength + " (expected: >= 0)"); - } - if (index < 0 || index > capacity() - fieldLength) { + if (isInvalid(index, fieldLength, capacity())) { throw new IndexOutOfBoundsException(String.format( "index: %d, length: %d (expected: range(0, %d))", index, fieldLength, capacity())); } @@ -1110,7 +1114,7 @@ public abstract class AbstractByteBuf extends ByteBuf { protected final void checkSrcIndex(int index, int length, int srcIndex, int srcCapacity) { checkIndex(index, length); - if (srcIndex < 0 || srcIndex > srcCapacity - length) { + if (isInvalid(srcIndex, length, srcCapacity)) { throw new IndexOutOfBoundsException(String.format( "srcIndex: %d, length: %d (expected: range(0, %d))", srcIndex, length, srcCapacity)); } @@ -1118,22 +1122,30 @@ public abstract class AbstractByteBuf extends ByteBuf { protected final void checkDstIndex(int index, int length, int dstIndex, int dstCapacity) { checkIndex(index, length); - if (dstIndex < 0 || dstIndex > dstCapacity - length) { + if (isInvalid(dstIndex, length, dstCapacity)) { throw new IndexOutOfBoundsException(String.format( "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 * {@linkplain #readableBytes() readable bytes} of this buffer is less * than the specified value. */ protected final void checkReadableBytes(int minimumReadableBytes) { - ensureAccessible(); if (minimumReadableBytes < 0) { throw new IllegalArgumentException("minimumReadableBytes: " + minimumReadableBytes + " (expected: >= 0)"); } + checkReadableBytes0(minimumReadableBytes); + } + + private void checkReadableBytes0(int minimumReadableBytes) { + ensureAccessible(); if (readerIndex > writerIndex - minimumReadableBytes) { throw new IndexOutOfBoundsException(String.format( "readerIndex(%d) + length(%d) exceeds writerIndex(%d): %s",