Update Optimize-Network-Manager

This commit is contained in:
Nassim Jahnke 2024-12-16 10:19:57 +01:00
parent a148433e1e
commit 797abd11dd
No known key found for this signature in database
GPG key ID: EF6771C01F6EF02F

View file

@ -27,34 +27,34 @@ and then catch exceptions and close if they fire.
Part of this commit was authored by: Spottedleaf, sandtechnology Part of this commit was authored by: Spottedleaf, sandtechnology
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index b624f001ba9d98c4dc68fcd66c0bc2de0a12308c..c4bb28857ee11dccc9924666634488044c666fd1 100644
--- a/src/main/java/net/minecraft/network/Connection.java --- a/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java +++ b/net/minecraft/network/Connection.java
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> { @@ -85,7 +85,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
private static final ProtocolInfo<ServerHandshakePacketListener> INITIAL_PROTOCOL = HandshakeProtocols.SERVERBOUND; private static final ProtocolInfo<ServerHandshakePacketListener> INITIAL_PROTOCOL = HandshakeProtocols.SERVERBOUND;
private final PacketFlow receiving; private final PacketFlow receiving;
private volatile boolean sendLoginDisconnect = true; private volatile boolean sendLoginDisconnect = true;
- private final Queue<Consumer<Connection>> pendingActions = Queues.newConcurrentLinkedQueue(); - private final Queue<Consumer<Connection>> pendingActions = Queues.newConcurrentLinkedQueue();
+ private final Queue<WrappedConsumer> pendingActions = Queues.newConcurrentLinkedQueue(); // Paper + private final Queue<WrappedConsumer> pendingActions = Queues.newConcurrentLinkedQueue(); // Paper - Optimize network
public Channel channel; public Channel channel;
public SocketAddress address; public SocketAddress address;
// Spigot Start // Spigot Start
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> { @@ -145,6 +145,10 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
public java.net.InetSocketAddress virtualHost; }
private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); // Paper - Disable explicit network manager flushing // Paper end - packet limiter
// Paper end @Nullable public SocketAddress haProxyAddress; // Paper - Add API to get player's proxy address
+ // Paper start - Optimize network + // Paper start - Optimize network
+ public boolean isPending = true; + public boolean isPending = true;
+ public boolean queueImmunity; + public boolean queueImmunity;
+ // Paper end - Optimize network + // Paper end - Optimize network
// Paper start - add utility methods public Connection(PacketFlow receiving) {
public final net.minecraft.server.level.ServerPlayer getPlayer() { this.receiving = receiving;
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> { @@ -425,11 +429,38 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
} }
public void send(Packet<?> packet, @Nullable PacketSendListener callbacks, boolean flush) { public void send(Packet<?> packet, @Nullable PacketSendListener listener, boolean flush) {
- if (this.isConnected()) { - if (this.isConnected()) {
- this.flushQueue(); - this.flushQueue();
+ // Paper start - Optimize network: Handle oversized packets better + // Paper start - Optimize network: Handle oversized packets better
@ -67,17 +67,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (connected && (InnerUtil.canSendImmediate(this, packet) + if (connected && (InnerUtil.canSendImmediate(this, packet)
+ || (io.papermc.paper.util.MCUtil.isMainThread() && packet.isReady() && this.pendingActions.isEmpty() + || (io.papermc.paper.util.MCUtil.isMainThread() && packet.isReady() && this.pendingActions.isEmpty()
+ && (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty())))) { + && (packet.getExtraPackets() == null || packet.getExtraPackets().isEmpty())))) {
this.sendPacket(packet, callbacks, flush); this.sendPacket(packet, listener, flush);
} else { } else {
- this.pendingActions.add((networkmanager) -> { - this.pendingActions.add(connection -> connection.sendPacket(packet, listener, flush));
- networkmanager.sendPacket(packet, callbacks, flush);
- });
- }
+ // Write the packets to the queue, then flush - antixray hooks there already + // Write the packets to the queue, then flush - antixray hooks there already
+ final java.util.List<Packet<?>> extraPackets = InnerUtil.buildExtraPackets(packet); + final java.util.List<Packet<?>> extraPackets = InnerUtil.buildExtraPackets(packet);
+ final boolean hasExtraPackets = extraPackets != null && !extraPackets.isEmpty(); + final boolean hasExtraPackets = extraPackets != null && !extraPackets.isEmpty();
+ if (!hasExtraPackets) { + if (!hasExtraPackets) {
+ this.pendingActions.add(new PacketSendAction(packet, callbacks, flush)); + this.pendingActions.add(new PacketSendAction(packet, listener, flush));
+ } else { + } else {
+ final java.util.List<PacketSendAction> actions = new java.util.ArrayList<>(1 + extraPackets.size()); + final java.util.List<PacketSendAction> actions = new java.util.ArrayList<>(1 + extraPackets.size());
+ actions.add(new PacketSendAction(packet, null, false)); // Delay the future listener until the end of the extra packets + actions.add(new PacketSendAction(packet, null, false)); // Delay the future listener until the end of the extra packets
@ -85,31 +82,30 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ for (int i = 0, len = extraPackets.size(); i < len;) { + for (int i = 0, len = extraPackets.size(); i < len;) {
+ final Packet<?> extraPacket = extraPackets.get(i); + final Packet<?> extraPacket = extraPackets.get(i);
+ final boolean end = ++i == len; + final boolean end = ++i == len;
+ actions.add(new PacketSendAction(extraPacket, end ? callbacks : null, end)); // Append listener to the end + actions.add(new PacketSendAction(extraPacket, end ? listener : null, end)); // Append listener to the end
+ } + }
+ +
+ this.pendingActions.addAll(actions); + this.pendingActions.addAll(actions);
+ } + }
+
+ this.flushQueue(); + this.flushQueue();
+ // Paper end - Optimize network + // Paper end - Optimize network
+ }
}
public void runOnceConnected(Consumer<Connection> task) {
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
this.flushQueue();
task.accept(this);
} else {
- this.pendingActions.add(task);
+ this.pendingActions.add(new WrappedConsumer(task)); // Paper - Optimize network
} }
}
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
} }
private void doSendPacket(Packet<?> packet, @Nullable PacketSendListener callbacks, boolean flush) { @@ -438,7 +469,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
this.flushQueue();
action.accept(this);
} else {
- this.pendingActions.add(action);
+ this.pendingActions.add(new WrappedConsumer(action)); // Paper - Optimize network
}
}
@@ -452,6 +483,14 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
}
private void doSendPacket(Packet<?> packet, @Nullable PacketSendListener sendListener, boolean flush) {
+ // Paper start - Optimize network + // Paper start - Optimize network
+ final net.minecraft.server.level.ServerPlayer player = this.getPlayer(); + final net.minecraft.server.level.ServerPlayer player = this.getPlayer();
+ if (!this.isConnected()) { + if (!this.isConnected()) {
@ -118,18 +114,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ try { + try {
+ // Paper end - Optimize network + // Paper end - Optimize network
ChannelFuture channelfuture = flush ? this.channel.writeAndFlush(packet) : this.channel.write(packet); ChannelFuture channelFuture = flush ? this.channel.writeAndFlush(packet) : this.channel.write(packet);
if (sendListener != null) {
if (callbacks != null) { channelFuture.addListener(future -> {
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> { @@ -467,14 +506,24 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
}); });
} }
+ // Paper start - Optimize network + // Paper start - Optimize network
+ if (packet.hasFinishListener()) { + if (packet.hasFinishListener()) {
+ channelfuture.addListener((ChannelFutureListener) channelFuture -> packet.onPacketDispatchFinish(player, channelFuture)); + channelFuture.addListener((ChannelFutureListener) future -> packet.onPacketDispatchFinish(player, future));
+ } + }
channelfuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE); channelFuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
+ } catch (final Exception e) { + } catch (final Exception e) {
+ LOGGER.error("NetworkException: {}", player, e); + LOGGER.error("NetworkException: {}", player, e);
+ this.disconnect(Component.translatable("disconnect.genericReason", "Internal Exception: " + e.getMessage())); + this.disconnect(Component.translatable("disconnect.genericReason", "Internal Exception: " + e.getMessage()));
@ -145,16 +141,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
- this.pendingActions.add(Connection::flush); - this.pendingActions.add(Connection::flush);
+ this.pendingActions.add(new WrappedConsumer(Connection::flush)); // Paper - Optimize network + this.pendingActions.add(new WrappedConsumer(Connection::flush)); // Paper - Optimize network
} }
} }
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -486,16 +535,57 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
}
} }
- private void flushQueue() { - private void flushQueue() {
- if (this.channel != null && this.channel.isOpen()) { - if (this.channel != null && this.channel.isOpen()) {
- Queue queue = this.pendingActions;
-
+ // Paper start - Optimize network: Rewrite this to be safer if ran off main thread + // Paper start - Optimize network: Rewrite this to be safer if ran off main thread
+ private boolean flushQueue() { + private boolean flushQueue() {
+ if (!this.isConnected()) { + if (!this.isConnected()) {
@ -165,7 +159,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } else if (this.isPending) { + } else if (this.isPending) {
+ // Should only happen during login/status stages + // Should only happen during login/status stages
synchronized (this.pendingActions) { synchronized (this.pendingActions) {
- Consumer consumer; - Consumer<Connection> consumer;
- while ((consumer = this.pendingActions.poll()) != null) {
- consumer.accept(this);
+ return this.processQueue(); + return this.processQueue();
+ } + }
+ } + }
@ -176,9 +172,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (this.pendingActions.isEmpty()) { + if (this.pendingActions.isEmpty()) {
+ return true; + return true;
+ } + }
+
- while ((consumer = (Consumer) this.pendingActions.poll()) != null) {
- consumer.accept(this);
+ // If we are on main, we are safe here in that nothing else should be processing queue off main anymore + // If we are on main, we are safe here in that nothing else should be processing queue off main anymore
+ // But if we are not on main due to login/status, the parent is synchronized on packetQueue + // But if we are not on main due to login/status, the parent is synchronized on packetQueue
+ final java.util.Iterator<WrappedConsumer> iterator = this.pendingActions.iterator(); + final java.util.Iterator<WrappedConsumer> iterator = this.pendingActions.iterator();
@ -199,12 +193,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ if (!packet.isReady()) { + if (!packet.isReady()) {
+ return false; + return false;
} }
+ } }
+
+ iterator.remove(); + iterator.remove();
+ if (queued.tryMarkConsumed()) { + if (queued.tryMarkConsumed()) {
+ queued.accept(this); + queued.accept(this);
} + }
} }
+ return true; + return true;
} }
@ -212,35 +206,35 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private static final int MAX_PER_TICK = io.papermc.paper.configuration.GlobalConfiguration.get().misc.maxJoinsPerTick; // Paper - Buffer joins to world private static final int MAX_PER_TICK = io.papermc.paper.configuration.GlobalConfiguration.get().misc.maxJoinsPerTick; // Paper - Buffer joins to world
private static int joinAttemptsThisTick; // Paper - Buffer joins to world private static int joinAttemptsThisTick; // Paper - Buffer joins to world
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> { @@ -561,6 +651,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
public void disconnect(DisconnectionDetails disconnectionInfo) {
// Spigot Start // Spigot Start
this.preparing = false; this.preparing = false;
+ this.clearPacketQueue(); // Paper - Optimize network
// Spigot End // Spigot End
+ this.clearPacketQueue(); // Paper - Optimize network
if (this.channel == null) { if (this.channel == null) {
this.delayedDisconnect = disconnectionInfo; this.delayedDisconnect = disconnectionDetails;
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> { }
@@ -749,7 +840,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
public void handleDisconnection() { public void handleDisconnection() {
if (this.channel != null && !this.channel.isOpen()) { if (this.channel != null && !this.channel.isOpen()) {
if (this.disconnectionHandled) { if (this.disconnectionHandled) {
- Connection.LOGGER.warn("handleDisconnection() called twice"); - LOGGER.warn("handleDisconnection() called twice");
+ // Connection.LOGGER.warn("handleDisconnection() called twice"); // Paper - Don't log useless message + // LOGGER.warn("handleDisconnection() called twice"); // Paper - Don't log useless message
} else { } else {
this.disconnectionHandled = true; this.disconnectionHandled = true;
PacketListener packetlistener = this.getPacketListener(); PacketListener packetListener = this.getPacketListener();
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> { @@ -760,7 +851,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
);
packetlistener1.onDisconnect(disconnectiondetails); packetListener1.onDisconnect(disconnectionDetails);
} }
- this.pendingActions.clear(); // Free up packet queue. - this.pendingActions.clear(); // Free up packet queue.
+ this.clearPacketQueue(); // Paper - Optimize network + this.clearPacketQueue(); // Paper - Optimize network
// Paper start - Add PlayerConnectionCloseEvent // Paper start - Add PlayerConnectionCloseEvent
final PacketListener packetListener = this.getPacketListener();
if (packetListener instanceof net.minecraft.server.network.ServerCommonPacketListenerImpl commonPacketListener) { if (packetListener instanceof net.minecraft.server.network.ServerCommonPacketListenerImpl commonPacketListener) {
@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> { /* Player was logged in, either game listener or configuration listener */
public void setBandwidthLogger(LocalSampleLogger log) { @@ -795,4 +886,93 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
this.bandwidthDebugMonitor = new BandwidthDebugMonitor(log); public void setBandwidthLogger(LocalSampleLogger bandwithLogger) {
this.bandwidthDebugMonitor = new BandwidthDebugMonitor(bandwithLogger);
} }
+ +
+ // Paper start - Optimize network + // Paper start - Optimize network
@ -332,11 +326,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ // Paper end - Optimize network + // Paper end - Optimize network
} }
diff --git a/src/main/java/net/minecraft/network/protocol/Packet.java b/src/main/java/net/minecraft/network/protocol/Packet.java diff --git a/net/minecraft/network/protocol/Packet.java b/net/minecraft/network/protocol/Packet.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 65ff8b9112ec76eeac48c679044fc02ae7d4ffeb..e4789584cbe43959681a8522c66eab58369bebd0 100644
--- a/src/main/java/net/minecraft/network/protocol/Packet.java --- a/net/minecraft/network/protocol/Packet.java
+++ b/src/main/java/net/minecraft/network/protocol/Packet.java +++ b/net/minecraft/network/protocol/Packet.java
@@ -0,0 +0,0 @@ public interface Packet<T extends PacketListener> { @@ -35,4 +35,32 @@ public interface Packet<T extends PacketListener> {
static <B extends ByteBuf, T extends Packet<?>> StreamCodec<B, T> codec(StreamMemberEncoder<B, T> encoder, StreamDecoder<B, T> decoder) { static <B extends ByteBuf, T extends Packet<?>> StreamCodec<B, T> codec(StreamMemberEncoder<B, T> encoder, StreamDecoder<B, T> decoder) {
return StreamCodec.ofMember(encoder, decoder); return StreamCodec.ofMember(encoder, decoder);
} }
@ -352,7 +346,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * @param player Null if not at PLAY stage yet + * @param player Null if not at PLAY stage yet
+ * @param future Can be null if packet was cancelled + * @param future Can be null if packet was cancelled
+ */ + */
+ default void onPacketDispatchFinish(@org.jetbrains.annotations.Nullable net.minecraft.server.level.ServerPlayer player, @org.jetbrains.annotations.Nullable io.netty.channel.ChannelFuture future) {} + default void onPacketDispatchFinish(@org.jetbrains.annotations.Nullable net.minecraft.server.level.ServerPlayer player, @org.jetbrains.annotations.Nullable io.netty.channel.ChannelFuture future) {
+ }
+ +
+ default boolean hasFinishListener() { + default boolean hasFinishListener() {
+ return false; + return false;
@ -368,28 +363,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ } + }
+ // Paper end + // Paper end
} }
diff --git a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java diff --git a/net/minecraft/server/network/ServerConnectionListener.java b/net/minecraft/server/network/ServerConnectionListener.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 index 18fa53903cd6500ae65d993a6fe7f49d6b069339..b68adf37af7172671163d4a8074d2bfa97724b4b 100644
--- a/src/main/java/net/minecraft/server/network/ServerConnectionListener.java --- a/net/minecraft/server/network/ServerConnectionListener.java
+++ b/src/main/java/net/minecraft/server/network/ServerConnectionListener.java +++ b/net/minecraft/server/network/ServerConnectionListener.java
@@ -0,0 +0,0 @@ public class ServerConnectionListener { @@ -66,11 +66,13 @@ public class ServerConnectionListener {
final List<Connection> connections = Collections.synchronizedList(Lists.newArrayList());
// Paper start - prevent blocking on adding a new connection while the server is ticking // Paper start - prevent blocking on adding a new connection while the server is ticking
private final java.util.Queue<Connection> pending = new java.util.concurrent.ConcurrentLinkedQueue<>(); private final java.util.Queue<Connection> pending = new java.util.concurrent.ConcurrentLinkedQueue<>();
+ private static final boolean disableFlushConsolidation = Boolean.getBoolean("Paper.disableFlushConsolidate"); // Paper - Optimize network + private static final boolean disableFlushConsolidation = Boolean.getBoolean("Paper.disableFlushConsolidate"); // Paper - Optimize network
private final void addPending() { private final void addPending() {
Connection connection; Connection connection;
while ((connection = pending.poll()) != null) { while ((connection = this.pending.poll()) != null) {
connections.add(connection); this.connections.add(connection);
+ connection.isPending = false; // Paper - Optimize network + connection.isPending = false; // Paper - Optimize network
} }
} }
// Paper end - prevent blocking on adding a new connection while the server is ticking // Paper end - prevent blocking on adding a new connection while the server is ticking
@@ -0,0 +0,0 @@ public class ServerConnectionListener { @@ -120,6 +122,7 @@ public class ServerConnectionListener {
; } catch (ChannelException var5) {
} }
+ if (!disableFlushConsolidation) channel.pipeline().addFirst(new io.netty.handler.flush.FlushConsolidationHandler()); // Paper - Optimize network + if (!disableFlushConsolidation) channel.pipeline().addFirst(new io.netty.handler.flush.FlushConsolidationHandler()); // Paper - Optimize network
ChannelPipeline channelpipeline = channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)); ChannelPipeline channelPipeline = channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30));
if (ServerConnectionListener.this.server.repliesToStatus()) {
if (ServerConnectionListener.this.server.repliesToStatus()) { channelPipeline.addLast("legacy_query", new LegacyQueryHandler(ServerConnectionListener.this.getServer()));