Skip extra buf copying entirely if wrapper had no changes

This commit is contained in:
Nassim Jahnke 2024-11-04 22:55:40 +01:00
parent 76db43cab3
commit 77f0826ec8
No known key found for this signature in database
GPG Key ID: EF6771C01F6EF02F
3 changed files with 40 additions and 12 deletions

View File

@ -61,6 +61,15 @@ public class VarIntType extends Type<Integer> implements TypeConverter<Integer>
buffer.writeByte(value); buffer.writeByte(value);
} }
public static int varIntLength(int value) {
int length = 1;
while ((value & MULTI_BYTE_BITS) != 0) {
length++;
value >>>= 7;
}
return length;
}
/** /**
* @deprecated use {@link #readPrimitive(ByteBuf)} for manual reading to avoid wrapping * @deprecated use {@link #readPrimitive(ByteBuf)} for manual reading to avoid wrapping
*/ */

View File

@ -29,8 +29,8 @@ import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.Direction; import com.viaversion.viaversion.api.protocol.packet.Direction;
import com.viaversion.viaversion.api.protocol.packet.PacketTracker; import com.viaversion.viaversion.api.protocol.packet.PacketTracker;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper; import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.type.Types; import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.VarIntType;
import com.viaversion.viaversion.exception.CancelException; import com.viaversion.viaversion.exception.CancelException;
import com.viaversion.viaversion.exception.InformativeException; import com.viaversion.viaversion.exception.InformativeException;
import com.viaversion.viaversion.protocol.packet.PacketWrapperImpl; import com.viaversion.viaversion.protocol.packet.PacketWrapperImpl;
@ -335,7 +335,7 @@ public class UserConnectionImpl implements UserConnection {
return; return;
} }
int id = Types.VAR_INT.readPrimitive(buf); final int id = Types.VAR_INT.readPrimitive(buf);
if (id == PacketWrapper.PASSTHROUGH_ID) { if (id == PacketWrapper.PASSTHROUGH_ID) {
if (!passthroughTokens.remove(Types.UUID.read(buf))) { if (!passthroughTokens.remove(Types.UUID.read(buf))) {
throw new IllegalArgumentException("Invalid token"); throw new IllegalArgumentException("Invalid token");
@ -343,29 +343,43 @@ public class UserConnectionImpl implements UserConnection {
return; return;
} }
PacketWrapperImpl wrapper = new PacketWrapperImpl(id, buf, this); final int valuesReaderIndex = buf.readerIndex();
State state = protocolInfo.getState(direction); final PacketWrapperImpl wrapper = new PacketWrapperImpl(id, buf, this);
try { try {
protocolInfo.getPipeline().transform(direction, state, wrapper); protocolInfo.getPipeline().transform(direction, protocolInfo.getState(direction), wrapper);
} catch (CancelException ex) { } catch (final CancelException ex) {
throw cancelSupplier.apply(ex); throw cancelSupplier.apply(ex);
} }
writeToBuffer(wrapper, buf); writeToBuffer(wrapper, buf, id, valuesReaderIndex);
} }
private void writeToBuffer(final PacketWrapperImpl wrapper, final ByteBuf buf) { private void writeToBuffer(final PacketWrapperImpl wrapper, final ByteBuf buf, final int originalId, final int originalReaderIndex) {
final int remainingBytes = buf.readableBytes();
if (buf.readerIndex() == originalReaderIndex && wrapper.areStoredPacketValuesEmpty()) {
if (wrapper.getId() == originalId) {
// No changes needed; just set the reader and writer indexes and we're done
buf.setIndex(0, originalReaderIndex + remainingBytes);
return;
}
if (VarIntType.varIntLength(wrapper.getId()) == VarIntType.varIntLength(originalId)) {
// If the var int encoded length is the same, simply replace the id at the head
buf.setIndex(0, 0);
Types.VAR_INT.writePrimitive(buf, wrapper.getId());
buf.writerIndex(originalReaderIndex + remainingBytes);
return;
}
}
// Instead of allocating a possible unnecessarily large buffer to write the wrapper contents to, // Instead of allocating a possible unnecessarily large buffer to write the wrapper contents to,
// only allocate the remaining bytes and write the rest to the original buf's head directly. // only allocate the remaining bytes and write the rest to the original buf's head directly.
final int remainingBytes = buf.readableBytes();
final ByteBuf remainingBuf = buf.alloc().buffer(remainingBytes); final ByteBuf remainingBuf = buf.alloc().buffer(remainingBytes);
try { try {
// Copy before modifying the buffer // Copy before modifying the buffer
remainingBuf.writeBytes(buf, remainingBytes); remainingBuf.writeBytes(buf, remainingBytes);
// Reset indexes, write wrapper contents, then the unread bytes // Reset indexes, write wrapper contents, then the unread bytes
buf.readerIndex(0); buf.setIndex(0, 0);
buf.writerIndex(0);
wrapper.writeProcessedValues(buf); wrapper.writeProcessedValues(buf);
buf.writeBytes(remainingBuf); buf.writeBytes(remainingBuf);
} finally { } finally {

View File

@ -228,6 +228,11 @@ public class PacketWrapperImpl implements PacketWrapper {
} }
} }
public boolean areStoredPacketValuesEmpty() {
// Check for read/added packet values, not the input buffer
return packetValues.isEmpty() && readableObjects.isEmpty();
}
public void writeProcessedValues(ByteBuf buffer) throws InformativeException { public void writeProcessedValues(ByteBuf buffer) throws InformativeException {
if (id != -1) { if (id != -1) {
Types.VAR_INT.writePrimitive(buffer, id); Types.VAR_INT.writePrimitive(buffer, id);