Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-11-16 21:10:30 +01:00
Unroll the VarInt writing loop
This is about as optimized as it can get. Thanks to @Leymooo for the idea, I simply expanded on it. We optimize for the common 1-3 byte cases, and punt more "complicated" cases to the original VarInt writing function we had before.
Dieser Commit ist enthalten in:
Ursprung
d42cc4f984
Commit
1cef82d54d
@ -120,15 +120,32 @@ public enum ProtocolUtils {
|
|||||||
* @param value the integer to write
|
* @param value the integer to write
|
||||||
*/
|
*/
|
||||||
public static void writeVarInt(ByteBuf buf, int value) {
|
public static void writeVarInt(ByteBuf buf, int value) {
|
||||||
// Inspired by https://richardstartin.github.io/posts/dont-use-protobuf-for-telemetry
|
int bytes = varIntBytes(value);
|
||||||
// This has been slightly modified in that we reduce the length to 32-bit only, since Velocity
|
// Optimization: focus on 1-3 byte VarInts as they are the most common
|
||||||
// doesn't look at any part of the Minecraft protocol that requires us to look at VarLongs.
|
if (bytes == 1) {
|
||||||
int continuationBytes = (31 - Integer.numberOfLeadingZeros(value)) / 7;
|
buf.writeByte(value & 0x7f);
|
||||||
for (int i = 0; i < continuationBytes; ++i) {
|
} else if (bytes == 2) {
|
||||||
buf.writeByte(((byte) ((value & 0x7F) | 0x80)));
|
int w = (value & 0x7F | 0x80) << 8 | (value >>> 7);
|
||||||
|
buf.writeShort(w);
|
||||||
|
} else if (bytes == 3) {
|
||||||
|
int w = (value & 0x7F | 0x80) << 16 | ((value >>> 7) & 0x7F | 0x80) << 8 | (value >>> 14);
|
||||||
|
buf.writeMedium(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;
|
value >>>= 7;
|
||||||
}
|
}
|
||||||
buf.writeByte((byte) value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String readString(ByteBuf buf) {
|
public static String readString(ByteBuf buf) {
|
||||||
|
@ -43,7 +43,8 @@ public class MinecraftVarintLengthEncoder extends MessageToByteEncoder<ByteBuf>
|
|||||||
@Override
|
@Override
|
||||||
protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, ByteBuf msg, boolean preferDirect)
|
protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, ByteBuf msg, boolean preferDirect)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
int anticipatedRequiredCapacity = 5 + msg.readableBytes();
|
int anticipatedRequiredCapacity = ProtocolUtils.varIntBytes(msg.readableBytes())
|
||||||
|
+ msg.readableBytes();
|
||||||
return IS_JAVA_CIPHER
|
return IS_JAVA_CIPHER
|
||||||
? ctx.alloc().heapBuffer(anticipatedRequiredCapacity)
|
? ctx.alloc().heapBuffer(anticipatedRequiredCapacity)
|
||||||
: ctx.alloc().directBuffer(anticipatedRequiredCapacity);
|
: ctx.alloc().directBuffer(anticipatedRequiredCapacity);
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren