geforkt von Mirrors/Velocity
Add highly-optimized VarInt writing method
Dieser Commit ist enthalten in:
Ursprung
6369a95ec9
Commit
150fd9a9cf
@ -120,7 +120,7 @@ public enum ProtocolUtils {
|
||||
* @param value the integer to write
|
||||
*/
|
||||
public static void writeVarInt(ByteBuf buf, int value) {
|
||||
// Optimization: focus on 1-3 byte VarInts as they are the most common
|
||||
// See https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/
|
||||
if ((value & (0xFFFFFFFF << 7)) == 0) {
|
||||
buf.writeByte(value);
|
||||
} else if ((value & (0xFFFFFFFF << 14)) == 0) {
|
||||
@ -129,30 +129,26 @@ public enum ProtocolUtils {
|
||||
} else if ((value & (0xFFFFFFFF << 21)) == 0) {
|
||||
int w = (value & 0x7F | 0x80) << 16 | ((value >>> 7) & 0x7F | 0x80) << 8 | (value >>> 14);
|
||||
buf.writeMedium(w);
|
||||
} else if ((value & (0xFFFFFFFF << 28)) == 0) {
|
||||
int w = (value & 0x7F | 0x80) << 24 | (((value >>> 7) & 0x7F | 0x80) << 16)
|
||||
| ((value >>> 14) & 0x7F | 0x80) << 8 | (value >>> 21);
|
||||
buf.writeInt(w);
|
||||
} else {
|
||||
// 4 and 5 byte VarInts aren't common so split those cases off
|
||||
writeVarIntUncommon(buf, value);
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeVarIntUncommon(ByteBuf buf, int value) {
|
||||
while (true) {
|
||||
if ((value & 0xFFFFFF80) == 0) {
|
||||
buf.writeByte(value);
|
||||
return;
|
||||
}
|
||||
|
||||
buf.writeByte(value & 0x7F | 0x80);
|
||||
value >>>= 7;
|
||||
int w = (value & 0x7F | 0x80) << 24 | ((value >>> 7) & 0x7F | 0x80) << 16
|
||||
| ((value >>> 14) & 0x7F | 0x80) << 8 | ((value >>> 21) & 0x7F | 0x80);
|
||||
buf.writeInt(w);
|
||||
buf.writeByte(value >>> 28);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes all integers as 3 bytes Minecraft-style VarInt to the specified {@code buf}.
|
||||
* Writes the specified {@code value} as a 21-bit Minecraft VarInt to the specified {@code buf}.
|
||||
* The upper 11 bits will be discarded.
|
||||
* @param buf the buffer to read from
|
||||
* @param value the integer to write
|
||||
*/
|
||||
public static void writeVarIntAs3Bytes(ByteBuf buf, int value) {
|
||||
public static void write21BitVarInt(ByteBuf buf, int value) {
|
||||
// See https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/
|
||||
int w = (value & 0x7F | 0x80) << 16 | ((value >>> 7) & 0x7F | 0x80) << 8 | (value >>> 14);
|
||||
buf.writeMedium(w);
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ public class MinecraftCompressorAndLengthEncoder extends MessageToByteEncoder<By
|
||||
throws DataFormatException {
|
||||
int uncompressed = msg.readableBytes();
|
||||
|
||||
ProtocolUtils.writeVarIntAs3Bytes(out, 0); // Dummy packet length
|
||||
ProtocolUtils.write21BitVarInt(out, 0); // Dummy packet length
|
||||
ProtocolUtils.writeVarInt(out, uncompressed);
|
||||
ByteBuf compatibleIn = MoreByteBufUtils.ensureCompatible(ctx.alloc(), compressor, msg);
|
||||
|
||||
@ -81,7 +81,7 @@ public class MinecraftCompressorAndLengthEncoder extends MessageToByteEncoder<By
|
||||
int writerIndex = out.writerIndex();
|
||||
int packetLength = out.readableBytes() - 3;
|
||||
out.writerIndex(0);
|
||||
ProtocolUtils.writeVarIntAs3Bytes(out, packetLength); // Rewrite packet length
|
||||
ProtocolUtils.write21BitVarInt(out, packetLength); // Rewrite packet length
|
||||
out.writerIndex(writerIndex);
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ public class ProtocolUtilsTest {
|
||||
|
||||
private void writeReadTest3Bytes(ByteBuf buf, int test) {
|
||||
buf.clear();
|
||||
ProtocolUtils.writeVarIntAs3Bytes(buf, test);
|
||||
ProtocolUtils.write21BitVarInt(buf, test);
|
||||
assertEquals(test, ProtocolUtils.readVarInt(buf));
|
||||
}
|
||||
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren