Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions Spigot-Server-Patches/0422-Flush-packets-async.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
From 944fc0cd274f7b65641b90b1a7d14ff885b93c00 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
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..88dc9eb83 100644
--- a/src/main/java/net/minecraft/server/NetworkManager.java
+++ b/src/main/java/net/minecraft/server/NetworkManager.java
@@ -66,6 +66,68 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet<?>> {
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<NetworkManager> needsUpdating = java.util.concurrent.ConcurrentHashMap.newKeySet();
+ private volatile boolean parked;
+
+ @Override
+ public void run() {
+ java.util.ArrayDeque<NetworkManager> keep = new java.util.ArrayDeque<>();
+ main_loop: for (;;) {
+ for (java.util.Iterator<NetworkManager> iterator = this.needsUpdating.iterator(); iterator.hasNext(); ) {
+ NetworkManager needsUpdate = iterator.next();
+ iterator.remove();
+
+ try {
+ if (!needsUpdate.sendPacketQueue()) {
+ keep.add(needsUpdate);
+ }
+ } catch (Throwable thr) {
+ MinecraftServer.LOGGER.error("Failed to flush packet queue", thr);
+ }
+ }
+
+ 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;
+ }
+
+ 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();
+ 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 +226,12 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet<?>> {
}

public void sendPacket(Packet<?> packet, @Nullable GenericFutureListener<? extends Future<? super Void>> 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.needsFlushing(this); // Paper - this is the packet flusher's job now
}

}
--
2.24.1.windows.2