From a6ec75b4cef43ce0ae5fda9998c816330c5fe21a Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Sat, 11 Jan 2020 21:46:43 -0800 Subject: [PATCH 1/2] Flush packets async Apparently sendPacket took 50% of the timings for entity tracker update, so offload that to the packet flusher thread. --- .../0422-Flush-packets-async.patch | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 Spigot-Server-Patches/0422-Flush-packets-async.patch diff --git a/Spigot-Server-Patches/0422-Flush-packets-async.patch b/Spigot-Server-Patches/0422-Flush-packets-async.patch new file mode 100644 index 000000000000..b9d69aabf867 --- /dev/null +++ b/Spigot-Server-Patches/0422-Flush-packets-async.patch @@ -0,0 +1,75 @@ +From bcee42af70c3b249f85bf943af8a718d0be31b76 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sun, 5 Jan 2020 17:17:41 -0800 +Subject: [PATCH] Flush packets async + +Apparently sendPacket took 50% of the timings for entity tracker +update, so offload that to the packet flusher thread. + +diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java +index 96a785af2..bf2281f79 100644 +--- a/src/main/java/net/minecraft/server/NetworkManager.java ++++ b/src/main/java/net/minecraft/server/NetworkManager.java +@@ -66,6 +66,45 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); + // Paper end + ++ // Paper start - flush packets async ++ static final class PacketFlusher extends Thread { ++ ++ public final java.util.Set needsUpdating = java.util.concurrent.ConcurrentHashMap.newKeySet(); ++ ++ @Override ++ public void run() { ++ java.util.ArrayDeque keep = new java.util.ArrayDeque<>(); ++ for (;;) { ++ for (java.util.Iterator iterator = this.needsUpdating.iterator(); iterator.hasNext();) { ++ NetworkManager needsUpdate = iterator.next(); ++ iterator.remove(); ++ ++ if (!needsUpdate.sendPacketQueue()) { ++ keep.add(needsUpdate); ++ } ++ } ++ ++ if (this.needsUpdating.isEmpty()) { ++ try { ++ Thread.sleep(1); ++ } catch (InterruptedException ex) {} ++ } ++ ++ for (int i = 0, len = keep.size(); i < len; ++i) { ++ this.needsUpdating.add(keep.poll()); ++ } ++ } ++ } ++ } ++ ++ static final PacketFlusher PACKET_FLUSHER = new PacketFlusher(); ++ static { ++ PACKET_FLUSHER.setName("Paper Packet flusher"); ++ PACKET_FLUSHER.setPriority(Thread.NORM_PRIORITY - 2); ++ PACKET_FLUSHER.start(); ++ } ++ // Paper end ++ + public NetworkManager(EnumProtocolDirection enumprotocoldirection) { + this.h = enumprotocoldirection; + } +@@ -164,11 +203,12 @@ public class NetworkManager extends SimpleChannelInboundHandler> { + } + + public void sendPacket(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { +- if (this.isConnected() && this.sendPacketQueue() && !(packet instanceof PacketPlayOutMapChunk && !((PacketPlayOutMapChunk) packet).isReady())) { // Paper - Async-Anti-Xray - Add chunk packets which are not ready or all packets if the packet queue contains chunk packets which are not ready to the packet queue and send the packets later in the right order ++ if (!(this.packetListener instanceof PlayerConnection) && this.isConnected() && this.sendPacketQueue() && !(packet instanceof PacketPlayOutMapChunk && !((PacketPlayOutMapChunk) packet).isReady())) { // Paper - Async-Anti-Xray - Add chunk packets which are not ready or all packets if the packet queue contains chunk packets which are not ready to the packet queue and send the packets later in the right order // Paper - this is the packet flusher's job now + //this.o(); // Paper - Async-Anti-Xray - Move to if statement (this.sendPacketQueue()) + this.b(packet, genericfuturelistener); + } else { + this.packetQueue.add(new NetworkManager.QueuedPacket(packet, genericfuturelistener)); ++ PACKET_FLUSHER.needsUpdating.add(this); // Paper - this is the packet flusher's job now + } + + } +-- +2.24.1 + From d15f3ecb806a60729dc709409617f4ffbcc0c523 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Mon, 13 Jan 2020 13:06:36 -0800 Subject: [PATCH 2/2] Use park/unpark --- .../0422-Flush-packets-async.patch | 55 +++++++++++++------ 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/Spigot-Server-Patches/0422-Flush-packets-async.patch b/Spigot-Server-Patches/0422-Flush-packets-async.patch index b9d69aabf867..cf4712b32110 100644 --- a/Spigot-Server-Patches/0422-Flush-packets-async.patch +++ b/Spigot-Server-Patches/0422-Flush-packets-async.patch @@ -1,4 +1,4 @@ -From bcee42af70c3b249f85bf943af8a718d0be31b76 Mon Sep 17 00:00:00 2001 +From 944fc0cd274f7b65641b90b1a7d14ff885b93c00 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Sun, 5 Jan 2020 17:17:41 -0800 Subject: [PATCH] Flush packets async @@ -7,10 +7,10 @@ Apparently sendPacket took 50% of the timings for entity tracker update, so offload that to the packet flusher thread. diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java -index 96a785af2..bf2281f79 100644 +index 96a785af2..88dc9eb83 100644 --- a/src/main/java/net/minecraft/server/NetworkManager.java +++ b/src/main/java/net/minecraft/server/NetworkManager.java -@@ -66,6 +66,45 @@ public class NetworkManager extends SimpleChannelInboundHandler> { +@@ -66,6 +66,68 @@ public class NetworkManager extends SimpleChannelInboundHandler> { private static boolean enableExplicitFlush = Boolean.getBoolean("paper.explicit-flush"); // Paper end @@ -18,31 +18,54 @@ index 96a785af2..bf2281f79 100644 + static final class PacketFlusher extends Thread { + + public final java.util.Set needsUpdating = java.util.concurrent.ConcurrentHashMap.newKeySet(); ++ private volatile boolean parked; + + @Override + public void run() { + java.util.ArrayDeque keep = new java.util.ArrayDeque<>(); -+ for (;;) { -+ for (java.util.Iterator iterator = this.needsUpdating.iterator(); iterator.hasNext();) { ++ main_loop: for (;;) { ++ for (java.util.Iterator iterator = this.needsUpdating.iterator(); iterator.hasNext(); ) { + NetworkManager needsUpdate = iterator.next(); + iterator.remove(); + -+ if (!needsUpdate.sendPacketQueue()) { -+ keep.add(needsUpdate); ++ try { ++ if (!needsUpdate.sendPacketQueue()) { ++ keep.add(needsUpdate); ++ } ++ } catch (Throwable thr) { ++ MinecraftServer.LOGGER.error("Failed to flush packet queue", thr); + } + } + -+ if (this.needsUpdating.isEmpty()) { -+ try { -+ Thread.sleep(1); -+ } catch (InterruptedException ex) {} ++ if (!keep.isEmpty()) { ++ for (int i = 0, len = keep.size(); i < len; ++i) { ++ this.needsUpdating.add(keep.poll()); ++ } ++ // not likely the packets are ready after 0.1ms ++ this.parked = true; ++ java.util.concurrent.locks.LockSupport.parkNanos(1000 * 1000); // 1e6, 1.0ms, 1000us ++ this.parked = false; ++ continue main_loop; + } + -+ for (int i = 0, len = keep.size(); i < len; ++i) { -+ this.needsUpdating.add(keep.poll()); ++ this.parked = true; ++ while (this.parked) { ++ if (!this.needsUpdating.isEmpty()) { ++ this.parked = false; ++ continue main_loop; ++ } ++ java.util.concurrent.locks.LockSupport.park(); + } + } + } ++ ++ public void needsFlushing(final NetworkManager networkManager) { ++ this.needsUpdating.add(networkManager); ++ if (this.parked) { ++ this.parked = false; ++ java.util.concurrent.locks.LockSupport.unpark(this); ++ } ++ } + } + + static final PacketFlusher PACKET_FLUSHER = new PacketFlusher(); @@ -56,7 +79,7 @@ index 96a785af2..bf2281f79 100644 public NetworkManager(EnumProtocolDirection enumprotocoldirection) { this.h = enumprotocoldirection; } -@@ -164,11 +203,12 @@ public class NetworkManager extends SimpleChannelInboundHandler> { +@@ -164,11 +226,12 @@ public class NetworkManager extends SimpleChannelInboundHandler> { } public void sendPacket(Packet packet, @Nullable GenericFutureListener> genericfuturelistener) { @@ -66,10 +89,10 @@ index 96a785af2..bf2281f79 100644 this.b(packet, genericfuturelistener); } else { this.packetQueue.add(new NetworkManager.QueuedPacket(packet, genericfuturelistener)); -+ PACKET_FLUSHER.needsUpdating.add(this); // Paper - this is the packet flusher's job now ++ PACKET_FLUSHER.needsFlushing(this); // Paper - this is the packet flusher's job now } } -- -2.24.1 +2.24.1.windows.2