forked from hpfxd/PandaSpigot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path0011-Allow-controlled-flushing-for-network-manager.patch
122 lines (113 loc) · 6.47 KB
/
0011-Allow-controlled-flushing-for-network-manager.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: hpfxd <[email protected]>
Date: Fri, 29 Oct 2021 07:56:48 -0400
Subject: [PATCH] Allow controlled flushing for network manager
Only make one flush call when emptying the packet queue too.
This patch will be used to optimise out flush calls in later patches.
diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java
index 067793583980d102f8310f6197a52d2f126d15d4..da76acafb5ffaea16f6a4dc28122c82f41bed318 100644
--- a/src/main/java/net/minecraft/server/NetworkManager.java
+++ b/src/main/java/net/minecraft/server/NetworkManager.java
@@ -80,6 +80,38 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet> {
public EnumProtocol protocol;
// PandaSpigot end
+ // PandaSpigot start - allow controlled flushing
+ volatile boolean canFlush = true;
+ private final java.util.concurrent.atomic.AtomicInteger packetWrites = new java.util.concurrent.atomic.AtomicInteger();
+ private int flushPacketsStart;
+ private final Object flushLock = new Object();
+
+ public void disableAutomaticFlush() {
+ synchronized (this.flushLock) {
+ this.flushPacketsStart = this.packetWrites.get(); // must be volatile and before canFlush = false
+ this.canFlush = false;
+ }
+ }
+
+ public void enableAutomaticFlush() {
+ synchronized (this.flushLock) {
+ this.canFlush = true;
+ if (this.packetWrites.get() != this.flushPacketsStart) { // must be after canFlush = true
+ this.flush(); // only make the flush call if we need to
+ }
+ }
+ }
+
+ private void flush() {
+ if (this.channel.eventLoop().inEventLoop()) {
+ this.channel.flush();
+ } else {
+ this.channel.eventLoop().execute(() -> {
+ this.channel.flush();
+ });
+ }
+ }
+ // PandaSpigot end
public NetworkManager(EnumProtocolDirection enumprotocoldirection) {
this.h = enumprotocoldirection;
}
@@ -223,6 +255,14 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet> {
private void dispatchPacket(final Packet packet, final GenericFutureListener<? extends Future<? super Void>>[] agenericfuturelistener) { this.a(packet, agenericfuturelistener); } // PandaSpigot - OBFHELPER
private void a(final Packet packet, final GenericFutureListener<? extends Future<? super Void>>[] agenericfuturelistener) {
+ // PandaSpigot start - add flush parameter
+ this.writePacket(packet, agenericfuturelistener, Boolean.TRUE);
+ }
+ private void writePacket(final Packet packet, final GenericFutureListener<? extends Future<? super Void>>[] agenericfuturelistener, Boolean flushConditional) {
+ this.packetWrites.getAndIncrement(); // must be before using canFlush
+ boolean effectiveFlush = flushConditional == null ? this.canFlush : flushConditional;
+ final boolean flush = effectiveFlush || packet instanceof PacketPlayOutKeepAlive || packet instanceof PacketPlayOutKickDisconnect; // no delay for certain packets
+ // PandaSpigot end - add flush parameter
final EnumProtocol enumprotocol = EnumProtocol.a(packet);
final EnumProtocol enumprotocol1 = (EnumProtocol) this.channel.attr(NetworkManager.c).get();
@@ -244,7 +284,7 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet> {
}
try {
// PandaSpigot end
- ChannelFuture channelfuture = this.channel.writeAndFlush(packet);
+ ChannelFuture channelfuture = (flush) ? this.channel.writeAndFlush(packet) : this.channel.write(packet); // PandaSpigot - add flush parameter
if (agenericfuturelistener != null) {
channelfuture.addListeners(agenericfuturelistener);
@@ -277,7 +317,7 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet> {
}
try {
// PandaSpigot end
- ChannelFuture channelfuture = NetworkManager.this.channel.writeAndFlush(packet);
+ ChannelFuture channelfuture = (flush) ? NetworkManager.this.channel.writeAndFlush(packet) : NetworkManager.this.channel.write(packet); // PandaSpigot - add flush parameter
if (agenericfuturelistener != null) {
channelfuture.addListeners(agenericfuturelistener);
@@ -320,22 +360,34 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet> {
}
private boolean processQueue() {
if (this.i.isEmpty()) return true;
+ // PandaSpigot start - make only one flush call per sendPacketQueue() call
+ final boolean needsFlush = this.canFlush; // make only one flush call per sendPacketQueue() call
+ boolean hasWrotePacket = false;
+ // PandaSpigot end
// 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
java.util.Iterator<QueuedPacket> iterator = this.i.iterator();
while (iterator.hasNext()) {
NetworkManager.QueuedPacket queued = iterator.next(); // poll -> peek
// Fix NPE (Spigot bug caused by handleDisconnection())
- if (queued == null) {
+ if (false && queued == null) { // PandaSpigot - diff on change, this logic is redundant: iterator guarantees ret of an element - on change, hook the flush logic here
return true;
}
Packet packet = queued.getPacket();
if (!packet.isReady()) {
+ // PandaSpigot start - make only one flush call per sendPacketQueue() call
+ if (hasWrotePacket && (needsFlush || this.canFlush)) {
+ this.flush();
+ }
+ // PandaSpigot end
return false;
} else {
iterator.remove();
- this.dispatchPacket(packet, queued.getGenericFutureListeners());
+ // PandaSpigot start - make only one flush call per sendPacketQueue() call
+ this.writePacket(packet, queued.getGenericFutureListeners(), (!iterator.hasNext() && (needsFlush || this.canFlush)) ? Boolean.TRUE : Boolean.FALSE);
+ hasWrotePacket = true;
+ // PandaSpigot end
}
}
return true;