From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com> Date: Mon, 3 Mar 2025 19:57:47 +0300 Subject: [PATCH] Leaf: Optimize Connection.flushQueue Original author - Taiyou06 Original patch - https://github.com/Winds-Studio/Leaf/pull/235 diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java index 5b46036868b6c9d082e35591e58735e16adaae62..a7f5c08726cce94c6a6c2a69028ad016a1bef30a 100644 --- a/net/minecraft/network/Connection.java +++ b/net/minecraft/network/Connection.java @@ -85,7 +85,11 @@ public class Connection extends SimpleChannelInboundHandler> { private static final ProtocolInfo INITIAL_PROTOCOL = HandshakeProtocols.SERVERBOUND; private final PacketFlow receiving; private volatile boolean sendLoginDisconnect = true; - private final Queue pendingActions = Queues.newConcurrentLinkedQueue(); // Paper - Optimize network + // DivineMC start - Optimize Connection.flushQueue + private final Queue pendingActions = org.bxteam.divinemc.DivineConfig.connectionFlushQueueRewrite + ? new java.util.ArrayDeque<>() + : Queues.newConcurrentLinkedQueue(); // Paper - Optimize network + // DivineMC end - Optimize Connection.flushQueue public Channel channel; public SocketAddress address; // Spigot start @@ -542,10 +546,16 @@ public class Connection extends SimpleChannelInboundHandler> { if (io.papermc.paper.util.MCUtil.isMainThread()) { return this.processQueue(); } else if (this.isPending) { - // Should only happen during login/status stages - synchronized (this.pendingActions) { - return this.processQueue(); + // DivineMC start - Leaf: Optimize Connection.flushQueue + if (org.bxteam.divinemc.DivineConfig.connectionFlushQueueRewrite) { + this.channel.eventLoop().execute(this::processQueue); + return false; + } else { + synchronized (this.pendingActions) { + return this.processQueue(); + } } + // DivineMC end - Leaf: Optimize Connection.flushQueue } return false; } @@ -555,33 +565,52 @@ public class Connection extends SimpleChannelInboundHandler> { return true; } - // 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 - final java.util.Iterator iterator = this.pendingActions.iterator(); - while (iterator.hasNext()) { - final WrappedConsumer queued = iterator.next(); // poll -> peek + // DivineMC start - Leaf: Optimize Connection.flushQueue + if (org.bxteam.divinemc.DivineConfig.connectionFlushQueueRewrite) { + WrappedConsumer queued; + while ((queued = this.pendingActions.poll()) != null) { + if (queued instanceof PacketSendAction packetSendAction) { + final Packet packet = packetSendAction.packet; + if (!packet.isReady()) { + this.pendingActions.add(queued); + return false; + } + } - // Fix NPE (Spigot bug caused by handleDisconnection()) - if (queued == null) { - return true; + if (queued.tryMarkConsumed()) { + queued.accept(this); + } } + } else { + // 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 + final java.util.Iterator iterator = this.pendingActions.iterator(); + while (iterator.hasNext()) { + final WrappedConsumer queued = iterator.next(); // poll -> peek + + // Fix NPE (Spigot bug caused by handleDisconnection()) + if (queued == null) { + return true; + } - if (queued.isConsumed()) { - continue; - } + if (queued.isConsumed()) { + continue; + } - if (queued instanceof PacketSendAction packetSendAction) { - final Packet packet = packetSendAction.packet; - if (!packet.isReady()) { - return false; + if (queued instanceof PacketSendAction packetSendAction) { + final Packet packet = packetSendAction.packet; + if (!packet.isReady()) { + return false; + } } - } - iterator.remove(); - if (queued.tryMarkConsumed()) { - queued.accept(this); + iterator.remove(); + if (queued.tryMarkConsumed()) { + queued.accept(this); + } } } + // DivineMC end - Leaf: Optimize Connection.flushQueue return true; } // Paper end - Optimize network @@ -914,15 +943,40 @@ public class Connection extends SimpleChannelInboundHandler> { // Paper start - Optimize network public void clearPacketQueue() { final net.minecraft.server.level.ServerPlayer player = getPlayer(); - for (final Consumer queuedAction : this.pendingActions) { - if (queuedAction instanceof PacketSendAction packetSendAction) { - final Packet packet = packetSendAction.packet; - if (packet.hasFinishListener()) { - packet.onPacketDispatchFinish(player, null); + + // DivineMC start - Leaf: Optimize Connection.flushQueue + if (org.bxteam.divinemc.DivineConfig.connectionFlushQueueRewrite) { + if (this.channel != null && !this.channel.eventLoop().inEventLoop()) { + this.channel.eventLoop().execute(this::clearPacketQueue); + return; + } + + java.util.List> queueSnapshot = new java.util.ArrayList<>(this.pendingActions); + + for (Consumer queuedAction : queueSnapshot) { + if (queuedAction instanceof PacketSendAction packetSendAction) { + final Packet packet = packetSendAction.packet; + if (packet.hasFinishListener()) { + packet.onPacketDispatchFinish(player, null); + } + } + } + + this.pendingActions.clear(); + } else { + synchronized (this.pendingActions) { + for (final Consumer queuedAction : this.pendingActions) { + if (queuedAction instanceof PacketSendAction packetSendAction) { + final Packet packet = packetSendAction.packet; + if (packet.hasFinishListener()) { + packet.onPacketDispatchFinish(player, null); + } + } } + this.pendingActions.clear(); } } - this.pendingActions.clear(); + // DivineMC end - Leaf: Optimize Connection.flushQueue } private static class InnerUtil { // Attempt to hide these methods from ProtocolLib, so it doesn't accidently pick them up.