From 82cf01b53f9273f2e1c284dc47e79b73ac83dedf Mon Sep 17 00:00:00 2001 From: md_5 Date: Tue, 28 Jan 2014 20:32:37 +1100 Subject: [PATCH] Implement Threaded Bulk Chunk Compression. This offloads chunk compression to a new thread, which should help with the pauses often seen when teleporting large amounts of players. --- CraftBukkit-Patches/0002-mc-dev-imports.patch | 45 +++++++- ...ment-Threaded-Bulk-Chunk-Compression.patch | 101 ++++++++++++++++++ 2 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 CraftBukkit-Patches/0104-Implement-Threaded-Bulk-Chunk-Compression.patch diff --git a/CraftBukkit-Patches/0002-mc-dev-imports.patch b/CraftBukkit-Patches/0002-mc-dev-imports.patch index 952f063..2f1e17a 100644 --- a/CraftBukkit-Patches/0002-mc-dev-imports.patch +++ b/CraftBukkit-Patches/0002-mc-dev-imports.patch @@ -1,4 +1,4 @@ -From 95e52dc06241d2a34781b0c4258c99d900ea3c44 Mon Sep 17 00:00:00 2001 +From 944e2150034a80c046ca0651cdf53d7cdf7e0b7f Mon Sep 17 00:00:00 2001 From: md_5 Date: Sun, 1 Dec 2013 15:10:48 +1100 Subject: [PATCH] mc-dev imports @@ -2077,6 +2077,49 @@ index 0000000..3691094 + return serverconnection.d; + } +} +diff --git a/src/main/java/net/minecraft/server/ServerConnectionChannel.java b/src/main/java/net/minecraft/server/ServerConnectionChannel.java +new file mode 100644 +index 0000000..fb95be4 +--- /dev/null ++++ b/src/main/java/net/minecraft/server/ServerConnectionChannel.java +@@ -0,0 +1,37 @@ ++package net.minecraft.server; ++ ++import net.minecraft.util.io.netty.channel.Channel; ++import net.minecraft.util.io.netty.channel.ChannelException; ++import net.minecraft.util.io.netty.channel.ChannelInitializer; ++import net.minecraft.util.io.netty.channel.ChannelOption; ++import net.minecraft.util.io.netty.handler.timeout.ReadTimeoutHandler; ++ ++class ServerConnectionChannel extends ChannelInitializer { ++ ++ final ServerConnection a; ++ ++ ServerConnectionChannel(ServerConnection serverconnection) { ++ this.a = serverconnection; ++ } ++ ++ protected void initChannel(Channel channel) { ++ try { ++ channel.config().setOption(ChannelOption.IP_TOS, Integer.valueOf(24)); ++ } catch (ChannelException channelexception) { ++ ; ++ } ++ ++ try { ++ channel.config().setOption(ChannelOption.TCP_NODELAY, Boolean.valueOf(false)); ++ } catch (ChannelException channelexception1) { ++ ; ++ } ++ ++ channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyPingHandler(this.a)).addLast("splitter", new PacketSplitter()).addLast("decoder", new PacketDecoder()).addLast("prepender", new PacketPrepender()).addLast("encoder", new PacketEncoder()); ++ NetworkManager networkmanager = new NetworkManager(false); ++ ++ ServerConnection.a(this.a).add(networkmanager); ++ channel.pipeline().addLast("packet_handler", networkmanager); ++ networkmanager.a((PacketListener) (new HandshakeListener(ServerConnection.b(this.a), networkmanager))); ++ } ++} diff --git a/src/main/java/net/minecraft/server/ServerStatisticManager.java b/src/main/java/net/minecraft/server/ServerStatisticManager.java new file mode 100644 index 0000000..2f980cb diff --git a/CraftBukkit-Patches/0104-Implement-Threaded-Bulk-Chunk-Compression.patch b/CraftBukkit-Patches/0104-Implement-Threaded-Bulk-Chunk-Compression.patch new file mode 100644 index 0000000..05ab06a --- /dev/null +++ b/CraftBukkit-Patches/0104-Implement-Threaded-Bulk-Chunk-Compression.patch @@ -0,0 +1,101 @@ +From 47f5faa5d3e3a74e8b85100c244001e7d1b8df0f Mon Sep 17 00:00:00 2001 +From: md_5 +Date: Tue, 28 Jan 2014 20:32:07 +1100 +Subject: [PATCH] Implement Threaded Bulk Chunk Compression + + +diff --git a/src/main/java/net/minecraft/server/PacketPlayOutMapChunkBulk.java b/src/main/java/net/minecraft/server/PacketPlayOutMapChunkBulk.java +index 30bf8a7..178a4ba 100644 +--- a/src/main/java/net/minecraft/server/PacketPlayOutMapChunkBulk.java ++++ b/src/main/java/net/minecraft/server/PacketPlayOutMapChunkBulk.java +@@ -6,7 +6,7 @@ import java.util.zip.DataFormatException; + import java.util.zip.Deflater; + import java.util.zip.Inflater; + +-public class PacketPlayOutMapChunkBulk extends Packet { ++public class PacketPlayOutMapChunkBulk extends Packet implements org.spigotmc.Compressible { // Spigot + + private int[] a; + private int[] b; +@@ -174,7 +174,7 @@ public class PacketPlayOutMapChunkBulk extends Packet { + } + + public void b(PacketDataSerializer packetdataserializer) throws IOException { // CraftBukkit - throws IOException +- compress(); // CraftBukkit ++ // compress(); // CraftBukkit // Spigot - removed + packetdataserializer.writeShort(this.a.length); + packetdataserializer.writeInt(this.size); + packetdataserializer.writeBoolean(this.h); +diff --git a/src/main/java/net/minecraft/server/ServerConnectionChannel.java b/src/main/java/net/minecraft/server/ServerConnectionChannel.java +index fb95be4..b18944e 100644 +--- a/src/main/java/net/minecraft/server/ServerConnectionChannel.java ++++ b/src/main/java/net/minecraft/server/ServerConnectionChannel.java +@@ -27,7 +27,8 @@ class ServerConnectionChannel extends ChannelInitializer { + ; + } + +- channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyPingHandler(this.a)).addLast("splitter", new PacketSplitter()).addLast("decoder", new PacketDecoder()).addLast("prepender", new PacketPrepender()).addLast("encoder", new PacketEncoder()); ++ channel.pipeline().addLast("timeout", new ReadTimeoutHandler(30)).addLast("legacy_query", new LegacyPingHandler(this.a)).addLast("splitter", new PacketSplitter()).addLast("decoder", new PacketDecoder()).addLast("prepender", new PacketPrepender()).addLast("encoder", new PacketEncoder()) ++ .addLast( new net.minecraft.util.io.netty.util.concurrent.DefaultEventExecutorGroup( org.spigotmc.SpigotConfig.compressionThreads, new com.google.common.util.concurrent.ThreadFactoryBuilder().setNameFormat( "Chunk Compressor #%d" ).setDaemon( true ).build() ), "compressor", new org.spigotmc.ChunkCompressor() ); // Spigot + NetworkManager networkmanager = new NetworkManager(false); + + ServerConnection.a(this.a).add(networkmanager); +diff --git a/src/main/java/org/spigotmc/ChunkCompressor.java b/src/main/java/org/spigotmc/ChunkCompressor.java +new file mode 100644 +index 0000000..71fcea6 +--- /dev/null ++++ b/src/main/java/org/spigotmc/ChunkCompressor.java +@@ -0,0 +1,21 @@ ++package org.spigotmc; ++ ++import net.minecraft.util.io.netty.channel.ChannelHandlerContext; ++import net.minecraft.util.io.netty.channel.ChannelOutboundHandlerAdapter; ++import net.minecraft.util.io.netty.channel.ChannelPromise; ++ ++public class ChunkCompressor extends ChannelOutboundHandlerAdapter ++{ ++ ++ @Override ++ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception ++ { ++ if ( msg instanceof Compressible ) ++ { ++ long start = System.currentTimeMillis(); ++ ( (Compressible) msg ).compress(); // TODO: Caching! ++ System.out.println( "Took: " + ( System.currentTimeMillis() - start ) + "ms to compress" ); ++ } ++ super.write( ctx, msg, promise ); ++ } ++} +diff --git a/src/main/java/org/spigotmc/Compressible.java b/src/main/java/org/spigotmc/Compressible.java +new file mode 100644 +index 0000000..f1cc789 +--- /dev/null ++++ b/src/main/java/org/spigotmc/Compressible.java +@@ -0,0 +1,7 @@ ++package org.spigotmc; ++ ++public interface Compressible ++{ ++ ++ void compress(); ++} +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 552266b..ca41dd9 100755 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -266,4 +266,11 @@ public class SpigotConfig + { + playerShuffle = getInt( "settings.player-shuffle", 0 ); + } ++ ++ public static int compressionThreads; ++ private static void compressionThreads() ++ { ++ compressionThreads = getInt( "settings.compression-threads", 4 ); ++ Bukkit.getLogger().log( Level.INFO, "Using {0} threads for async chunk compression", compressionThreads ); ++ } + } +-- +1.8.3.2 +