Reduce varint reading cost from max(1, 2n) to n+1 operations on ByteBuf

The previous code, in an attempt to avoid exceptions, checked in.isReadable() each iteration of the loop. This isn't very efficient since it's possible for us to know the maximum size of the varint to read: it's the minimum of either the largest size a varint can be (5 bytes) or the size of the remaining readable bytes in the buffer.
This commit is contained in:
Andrew Steinborn
2020-08-21 01:05:04 -04:00
parent ade9deec47
commit a6ddc137ee
2 changed files with 5 additions and 13 deletions

View File

@@ -67,22 +67,16 @@ public enum ProtocolUtils {
*/ */
public static int readVarIntSafely(ByteBuf buf) { public static int readVarIntSafely(ByteBuf buf) {
int i = 0; int i = 0;
int j = 0; int maxRead = Math.min(5, buf.readableBytes());
while (true) { for (int j = 0; j < maxRead; j++) {
if (!buf.isReadable()) {
return Integer.MIN_VALUE;
}
int k = buf.readByte(); int k = buf.readByte();
i |= (k & 0x7F) << j++ * 7; i |= (k & 0x7F) << j * 7;
if (j > 5) {
return Integer.MIN_VALUE;
}
if ((k & 0x80) != 128) { if ((k & 0x80) != 128) {
break;
}
}
return i; return i;
} }
}
return Integer.MIN_VALUE;
}
/** /**
* Writes a Minecraft-style VarInt to the specified {@code buf}. * Writes a Minecraft-style VarInt to the specified {@code buf}.

View File

@@ -42,8 +42,6 @@ public class MinecraftVarintFrameDecoder extends ByteToMessageDecoder {
if (in.isReadable(minimumRead)) { if (in.isReadable(minimumRead)) {
out.add(in.retainedSlice(varintEnd + 1, reader.readVarint)); out.add(in.retainedSlice(varintEnd + 1, reader.readVarint));
in.skipBytes(minimumRead); in.skipBytes(minimumRead);
} else {
return;
} }
} }
} else if (reader.result == DecodeResult.TOO_BIG) { } else if (reader.result == DecodeResult.TOO_BIG) {