From 052131c1fa4b20b7a125c1c52dbe55872091a699 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sun, 24 Jan 2016 11:22:39 +1100 Subject: [PATCH] Reduce amount of memcpy within proxy pipeline. --- .../bungee/protocol/MinecraftDecoder.java | 20 ++++++------ .../net/md_5/bungee/protocol/Protocol.java | 12 ++----- .../bungee/protocol/Varint21FrameDecoder.java | 7 ++-- .../bungee/compress/PacketDecompressor.java | 32 ++++++++++++------- 4 files changed, 34 insertions(+), 37 deletions(-) diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftDecoder.java b/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftDecoder.java index f9610f57..7911953d 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftDecoder.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/MinecraftDecoder.java @@ -13,7 +13,7 @@ public class MinecraftDecoder extends MessageToMessageDecoder @Setter private Protocol protocol; - private boolean server; + private final boolean server; @Setter private int protocolVersion; @@ -21,18 +21,18 @@ public class MinecraftDecoder extends MessageToMessageDecoder protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { Protocol.DirectionData prot = ( server ) ? protocol.TO_SERVER : protocol.TO_CLIENT; - ByteBuf copy = in.copy(); // TODO + ByteBuf slice = in.slice().retain(); try { int packetId = DefinedPacket.readVarInt( in ); - DefinedPacket packet = null; - if ( prot.hasPacket( packetId ) ) + DefinedPacket packet = prot.createPacket( packetId ); + if ( packet != null ) { - packet = prot.createPacket( packetId ); packet.read( in, prot.getDirection(), protocolVersion ); - if ( in.readableBytes() != 0 ) + + if ( in.isReadable() ) { throw new BadPacketException( "Did not read all bytes from packet " + packet.getClass() + " " + packetId + " Protocol " + protocol + " Direction " + prot ); } @@ -41,13 +41,13 @@ public class MinecraftDecoder extends MessageToMessageDecoder in.skipBytes( in.readableBytes() ); } - out.add( new PacketWrapper( packet, copy ) ); - copy = null; + out.add( new PacketWrapper( packet, slice ) ); + slice = null; } finally { - if ( copy != null ) + if ( slice != null ) { - copy.release(); + slice.release(); } } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java b/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java index 128d3934..570ccb52 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java @@ -120,25 +120,17 @@ public enum Protocol private final Class[] packetClasses = new Class[ MAX_PACKET_ID ]; private final Constructor[] packetConstructors = new Constructor[ MAX_PACKET_ID ]; - public boolean hasPacket(int id) - { - return id < MAX_PACKET_ID && packetConstructors[id] != null; - } - public final DefinedPacket createPacket(int id) { if ( id > MAX_PACKET_ID ) { throw new BadPacketException( "Packet with id " + id + " outside of range " ); } - if ( packetConstructors[id] == null ) - { - throw new BadPacketException( "No packet with id " + id ); - } + Constructor constructor = packetConstructors[id]; try { - return packetConstructors[id].newInstance(); + return ( constructor == null ) ? null : constructor.newInstance(); } catch ( ReflectiveOperationException ex ) { throw new BadPacketException( "Could not construct packet with id " + id, ex ); diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/Varint21FrameDecoder.java b/protocol/src/main/java/net/md_5/bungee/protocol/Varint21FrameDecoder.java index 0f3b5b65..d9f6d52e 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/Varint21FrameDecoder.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/Varint21FrameDecoder.java @@ -40,11 +40,8 @@ public class Varint21FrameDecoder extends ByteToMessageDecoder return; } else { - // TODO: Really should be a slice! - ByteBuf dst = ctx.alloc().directBuffer( length ); - in.readBytes( dst ); - - out.add( dst ); + out.add( in.slice( in.readerIndex(), length ).retain() ); + in.skipBytes( length ); return; } } diff --git a/proxy/src/main/java/net/md_5/bungee/compress/PacketDecompressor.java b/proxy/src/main/java/net/md_5/bungee/compress/PacketDecompressor.java index 4f33bc79..21b3ea2b 100644 --- a/proxy/src/main/java/net/md_5/bungee/compress/PacketDecompressor.java +++ b/proxy/src/main/java/net/md_5/bungee/compress/PacketDecompressor.java @@ -1,13 +1,14 @@ package net.md_5.bungee.compress; +import com.google.common.base.Preconditions; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.ByteToMessageDecoder; +import io.netty.handler.codec.MessageToMessageDecoder; import java.util.List; import net.md_5.bungee.jni.zlib.BungeeZlib; import net.md_5.bungee.protocol.DefinedPacket; -public class PacketDecompressor extends ByteToMessageDecoder +public class PacketDecompressor extends MessageToMessageDecoder { private final BungeeZlib zlib = CompressFactory.zlib.newInstance(); @@ -19,7 +20,7 @@ public class PacketDecompressor extends ByteToMessageDecoder } @Override - public void handlerRemoved0(ChannelHandlerContext ctx) throws Exception + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { zlib.free(); } @@ -27,22 +28,29 @@ public class PacketDecompressor extends ByteToMessageDecoder @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { - if ( in.readableBytes() == 0 ) - { - return; - } - int size = DefinedPacket.readVarInt( in ); if ( size == 0 ) { - out.add( in.copy() ); - in.readerIndex( in.writerIndex() ); + out.add( in.slice().retain() ); + in.skipBytes( in.readableBytes() ); } else { ByteBuf decompressed = ctx.alloc().directBuffer(); - zlib.process( in, decompressed ); - out.add( decompressed ); + try + { + zlib.process( in, decompressed ); + Preconditions.checkState( decompressed.readableBytes() == size, "Decompressed packet size mismatch" ); + + out.add( decompressed ); + decompressed = null; + } finally + { + if ( decompressed != null ) + { + decompressed.release(); + } + } } } }