Few fixes, tweaks for Netty

This commit is contained in:
md_5 2013-02-19 19:38:18 +11:00
parent a89be1da7d
commit ad40d85a05

View File

@ -1,23 +1,51 @@
From 632f1fe0d5566c3eb3df1f3ad1cd0619225e5f5f Mon Sep 17 00:00:00 2001 From 5469d039435d438a20d93aaa6724f420f6b24f25 Mon Sep 17 00:00:00 2001
From: md_5 <md_5@live.com.au> From: md_5 <md_5@live.com.au>
Date: Thu, 14 Feb 2013 17:32:20 +1100 Date: Thu, 14 Feb 2013 17:32:20 +1100
Subject: [PATCH] Netty Subject: [PATCH] Netty Implement an uber efficient network engine based on the
Java NIO framework Netty. This is basically a complete rewrite of the
Minecraft network engine with many distinct advantages. First and foremost,
there will no longer be the horrid, and redundant case of 2, or even at
times, 3 threads per a connection. Instead low level select/epoll based NIO
is used. The number of threads used for network reading and writing will
scale automatically to the number of cores for use on your server. In most
cases this will be around 8 threads for a 4 core server, much better than the
up to 1000 threads that could be in use at one time with the old engine. To
facilitate asynchronous packet sending or receiving (currently only chat), a
thread pool of 16 threads is kept handy. == Plugin incompatibilities As a
side effect of this change, plugins which rely on very specific
implementation level details within Minecraft are broken. At this point in
time, TagAPI and ProtocolLib are affected. If you are a user of ProtocolLib
you are advised to update to the latest build, where full support is enabled.
If you are a user of TagAPI, support has not yet been added, so you will need
to install the updated ProtocolLib so that TagAPI may use its functions. ==
Stability The code within this commit has been very lightly tested in
production (300 players for approximately 24 hours), however it is not
guaranteed to be free from all bugs. If you experence weird connection
behaviour, reporting the bug and steps to reproduce are advised. You are also
free to downgrade to the latest recommend build, which is guaranteed to be
stable. == Summary This commit provides a reduction in threads, which gives
the CPU / operating system more time to allocate to the main server threads,
as well as various other side benefits such as chat thread pooling and a
slight reduction in latency. This commit is licensed under the Creative
Commons Attribution-ShareAlike 3.0 Unported license.
--- ---
pom.xml | 5 + pom.xml | 5 +
.../java/net/minecraft/server/DedicatedServer.java | 2 +- .../java/net/minecraft/server/DedicatedServer.java | 4 +-
.../net/minecraft/server/Packet51MapChunk.java | 2 +- .../net/minecraft/server/Packet51MapChunk.java | 2 +-
.../net/minecraft/server/Packet56MapChunkBulk.java | 2 +- .../net/minecraft/server/Packet56MapChunkBulk.java | 2 +-
.../net/minecraft/server/PendingConnection.java | 13 +- .../net/minecraft/server/PendingConnection.java | 13 +-
.../net/minecraft/server/ThreadCommandReader.java | 1 +
.../craftbukkit/scheduler/CraftScheduler.java | 2 +-
src/main/java/org/spigotmc/netty/CipherCodec.java | 65 ++++++ src/main/java/org/spigotmc/netty/CipherCodec.java | 65 ++++++
.../org/spigotmc/netty/NettyNetworkManager.java | 228 +++++++++++++++++++ .../org/spigotmc/netty/NettyNetworkManager.java | 210 +++++++++++++++++
.../org/spigotmc/netty/NettyServerConnection.java | 105 +++++++++ .../org/spigotmc/netty/NettyServerConnection.java | 106 +++++++++
.../org/spigotmc/netty/NettySocketAdaptor.java | 248 +++++++++++++++++++++ .../org/spigotmc/netty/NettySocketAdaptor.java | 248 +++++++++++++++++++++
.../java/org/spigotmc/netty/PacketDecoder.java | 63 ++++++ .../java/org/spigotmc/netty/PacketDecoder.java | 63 ++++++
.../java/org/spigotmc/netty/PacketEncoder.java | 43 ++++ .../java/org/spigotmc/netty/PacketEncoder.java | 43 ++++
.../java/org/spigotmc/netty/PacketListener.java | 100 +++++++++ .../java/org/spigotmc/netty/PacketListener.java | 100 +++++++++
src/main/java/org/spigotmc/netty/ReadState.java | 16 ++ src/main/java/org/spigotmc/netty/ReadState.java | 16 ++
13 files changed, 885 insertions(+), 7 deletions(-) 15 files changed, 871 insertions(+), 9 deletions(-)
create mode 100644 src/main/java/org/spigotmc/netty/CipherCodec.java create mode 100644 src/main/java/org/spigotmc/netty/CipherCodec.java
create mode 100644 src/main/java/org/spigotmc/netty/NettyNetworkManager.java create mode 100644 src/main/java/org/spigotmc/netty/NettyNetworkManager.java
create mode 100644 src/main/java/org/spigotmc/netty/NettyServerConnection.java create mode 100644 src/main/java/org/spigotmc/netty/NettyServerConnection.java
@ -44,9 +72,18 @@ index f17bd19..6b314ec 100644
<!-- This builds a completely 'ready to start' jar with all dependencies inside --> <!-- This builds a completely 'ready to start' jar with all dependencies inside -->
diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java
index bd0377a..68feb71 100644 index bd0377a..729177b 100644
--- a/src/main/java/net/minecraft/server/DedicatedServer.java --- a/src/main/java/net/minecraft/server/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/DedicatedServer.java
@@ -32,7 +32,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer
public DedicatedServer(joptsimple.OptionSet options) {
super(options);
// CraftBukkit end
- new ThreadSleepForever(this);
+ // new ThreadSleepForever(this); // Spigot
}
protected boolean init() throws java.net.UnknownHostException { // CraftBukkit - throws UnknownHostException
@@ -93,7 +93,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer @@ -93,7 +93,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer
log.info("Starting Minecraft server on " + (this.getServerIp().length() == 0 ? "*" : this.getServerIp()) + ":" + this.G()); log.info("Starting Minecraft server on " + (this.getServerIp().length() == 0 ? "*" : this.getServerIp()) + ":" + this.G());
@ -122,6 +159,31 @@ index 8413a15..70fe839 100644
// CraftBukkit start - fix decompile issues, don't create a list from an array // CraftBukkit start - fix decompile issues, don't create a list from an array
Object[] list = new Object[] { 1, 51, this.server.getVersion(), pingEvent.getMotd(), playerlist.getPlayerCount(), pingEvent.getMaxPlayers() }; Object[] list = new Object[] { 1, 51, this.server.getVersion(), pingEvent.getMotd(), playerlist.getPlayerCount(), pingEvent.getMaxPlayers() };
diff --git a/src/main/java/net/minecraft/server/ThreadCommandReader.java b/src/main/java/net/minecraft/server/ThreadCommandReader.java
index 64eaa4c..fbf6fe6 100644
--- a/src/main/java/net/minecraft/server/ThreadCommandReader.java
+++ b/src/main/java/net/minecraft/server/ThreadCommandReader.java
@@ -11,6 +11,7 @@ class ThreadCommandReader extends Thread {
final DedicatedServer server;
ThreadCommandReader(DedicatedServer dedicatedserver) {
+ super("Command Reader Thread"); // Spigot
this.server = dedicatedserver;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
index 0a5c61a..35badf3 100644
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
@@ -70,7 +70,7 @@ public class CraftScheduler implements BukkitScheduler {
*/
private final ConcurrentHashMap<Integer, CraftTask> runners = new ConcurrentHashMap<Integer, CraftTask>();
private volatile int currentTick = -1;
- private final Executor executor = Executors.newCachedThreadPool();
+ private final Executor executor = Executors.newCachedThreadPool(new com.google.common.util.concurrent.ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %1$d").build()); // Spigot
private CraftAsyncDebugger debugHead = new CraftAsyncDebugger(-1, null, null) {@Override StringBuilder debugTo(StringBuilder string) {return string;}};
private CraftAsyncDebugger debugTail = debugHead;
private static final int RECENT_TICKS;
diff --git a/src/main/java/org/spigotmc/netty/CipherCodec.java b/src/main/java/org/spigotmc/netty/CipherCodec.java diff --git a/src/main/java/org/spigotmc/netty/CipherCodec.java b/src/main/java/org/spigotmc/netty/CipherCodec.java
new file mode 100644 new file mode 100644
index 0000000..f25af14 index 0000000..f25af14
@ -195,12 +257,13 @@ index 0000000..f25af14
+} +}
diff --git a/src/main/java/org/spigotmc/netty/NettyNetworkManager.java b/src/main/java/org/spigotmc/netty/NettyNetworkManager.java diff --git a/src/main/java/org/spigotmc/netty/NettyNetworkManager.java b/src/main/java/org/spigotmc/netty/NettyNetworkManager.java
new file mode 100644 new file mode 100644
index 0000000..adfd877 index 0000000..0edb062
--- /dev/null --- /dev/null
+++ b/src/main/java/org/spigotmc/netty/NettyNetworkManager.java +++ b/src/main/java/org/spigotmc/netty/NettyNetworkManager.java
@@ -0,0 +1,228 @@ @@ -0,0 +1,210 @@
+package org.spigotmc.netty; +package org.spigotmc.netty;
+ +
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import io.netty.channel.Channel; +import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundMessageHandlerAdapter; +import io.netty.channel.ChannelInboundMessageHandlerAdapter;
@ -208,8 +271,6 @@ index 0000000..adfd877
+import java.net.Socket; +import java.net.Socket;
+import java.net.SocketAddress; +import java.net.SocketAddress;
+import java.security.PrivateKey; +import java.security.PrivateKey;
+import java.util.AbstractList;
+import java.util.List;
+import java.util.Queue; +import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ExecutorService; +import java.util.concurrent.ExecutorService;
@ -231,28 +292,12 @@ index 0000000..adfd877
+ */ + */
+public class NettyNetworkManager extends ChannelInboundMessageHandlerAdapter<Packet> implements INetworkManager { +public class NettyNetworkManager extends ChannelInboundMessageHandlerAdapter<Packet> implements INetworkManager {
+ +
+ private static final ExecutorService threadPool = Executors.newCachedThreadPool(); + private static final ExecutorService threadPool = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("Async Packet Handler - %1$d").build());
+ private static final MinecraftServer server = MinecraftServer.getServer(); + private static final MinecraftServer server = MinecraftServer.getServer();
+ private static final PrivateKey key = server.F().getPrivate(); + private static final PrivateKey key = server.F().getPrivate();
+ private static final NettyServerConnection serverConnection = (NettyServerConnection) server.ae(); + private static final NettyServerConnection serverConnection = (NettyServerConnection) server.ae();
+ /*========================================================================*/ + /*========================================================================*/
+ private final Queue<Packet> syncPackets = new ConcurrentLinkedQueue<Packet>(); + private final Queue<Packet> syncPackets = new ConcurrentLinkedQueue<Packet>();
+ private final List<Packet> highPriorityQueue = new AbstractList<Packet>() {
+ @Override
+ public void add(int index, Packet element) {
+ // NOP
+ }
+
+ @Override
+ public Packet get(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int size() {
+ return 0;
+ }
+ };
+ private volatile boolean connected; + private volatile boolean connected;
+ private Channel channel; + private Channel channel;
+ private SocketAddress address; + private SocketAddress address;
@ -337,7 +382,6 @@ index 0000000..adfd877
+ packet = PacketListener.callQueued(this, connection, packet); + packet = PacketListener.callQueued(this, connection, packet);
+ // If handler indicates packet send + // If handler indicates packet send
+ if (packet != null) { + if (packet != null) {
+ highPriorityQueue.add(packet);
+ channel.write(packet); + channel.write(packet);
+ +
+ // If needed, check and prepare encryption phase + // If needed, check and prepare encryption phase
@ -429,12 +473,13 @@ index 0000000..adfd877
+} +}
diff --git a/src/main/java/org/spigotmc/netty/NettyServerConnection.java b/src/main/java/org/spigotmc/netty/NettyServerConnection.java diff --git a/src/main/java/org/spigotmc/netty/NettyServerConnection.java b/src/main/java/org/spigotmc/netty/NettyServerConnection.java
new file mode 100644 new file mode 100644
index 0000000..4f08e23 index 0000000..459919a
--- /dev/null --- /dev/null
+++ b/src/main/java/org/spigotmc/netty/NettyServerConnection.java +++ b/src/main/java/org/spigotmc/netty/NettyServerConnection.java
@@ -0,0 +1,105 @@ @@ -0,0 +1,106 @@
+package org.spigotmc.netty; +package org.spigotmc.netty;
+ +
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import io.netty.bootstrap.ServerBootstrap; +import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.Channel; +import io.netty.channel.Channel;
+import io.netty.channel.ChannelException; +import io.netty.channel.ChannelException;
@ -488,7 +533,7 @@ index 0000000..4f08e23
+ .addLast("encoder", new PacketEncoder()) + .addLast("encoder", new PacketEncoder())
+ .addLast("manager", new NettyNetworkManager()); + .addLast("manager", new NettyNetworkManager());
+ } + }
+ }).group(new NioEventLoopGroup(3)).localAddress(host, port).bind(); + }).group(new NioEventLoopGroup(1, new ThreadFactoryBuilder().setNameFormat("Netty IO Thread - %1$d").build())).localAddress(host, port).bind();
+ } + }
+ +
+ /** + /**