From 35f085a01799b79b64b769b745264a839ac348df Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Sat, 5 Mar 2016 16:10:11 -0600 Subject: [PATCH] Remove our own changes to the chunk save queue --- .../0077-Chunk-save-queue-improvements.patch | 169 ------------------ 1 file changed, 169 deletions(-) delete mode 100644 Spigot-Server-Patches/0077-Chunk-save-queue-improvements.patch diff --git a/Spigot-Server-Patches/0077-Chunk-save-queue-improvements.patch b/Spigot-Server-Patches/0077-Chunk-save-queue-improvements.patch deleted file mode 100644 index be648fe894..0000000000 --- a/Spigot-Server-Patches/0077-Chunk-save-queue-improvements.patch +++ /dev/null @@ -1,169 +0,0 @@ -From 15f73df80f65604080b217caa144ce218bffc96f Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Fri, 4 Mar 2016 18:18:37 -0600 -Subject: [PATCH] Chunk save queue improvements - -For some unknown reason, Minecraft is sleeping 10ms between every single chunk being saved to disk. -Under high chunk load/unload activity (lots of movement / teleporting), this causes the chunk unload queue -to build up in size. - -This has multiple impacts: -1) Performance of the unload queue itself - The save thread is pretty ineffecient for how it accesses it - By letting the queue get larger, checking and popping work off the queue can get less performant. -2) Performance of chunk loading - As with #1, chunk loads also have to check this queue when loading - chunk data so that it doesn't load stale data if new data is pending write to disk. -3) Memory Usage - The entire chunk has been serialized to NBT, and now sits in this queue. This leads to - elevated memory usage, and then the objects used in the serialization sit around longer than needed, - resulting in promotion to Old Generation instead of dying young. - -If there is work to do, then the thread should be doing its work, and only sleep when it is done. - -Additionally, optimize the ChunkRegionLoader queue to reduce lock contention (issue with 1.9) - -diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java -index 62f4631..ed49d83 100644 ---- a/src/main/java/com/destroystokyo/paper/PaperConfig.java -+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java -@@ -164,4 +164,10 @@ public class PaperConfig { - } - return time; - } -+ -+ public static boolean enableFileIOThreadSleep; -+ private static void enableFileIOThreadSleep() { -+ enableFileIOThreadSleep = getBoolean("settings.sleep-between-chunk-saves", false); -+ if (enableFileIOThreadSleep) Bukkit.getLogger().info("Enabled sleeping between chunk saves, beware of memory issues"); -+ } - } -diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -index 5bd6ce0..336e780 100644 ---- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java -+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java -@@ -11,14 +11,17 @@ import java.util.List; - import java.util.Map; - import java.util.Set; - import java.util.concurrent.ConcurrentHashMap; -+import java.util.concurrent.ConcurrentLinkedQueue; // Paper - import org.apache.logging.log4j.LogManager; - import org.apache.logging.log4j.Logger; - - public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { - -+ private ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue(); // Paper - Chunk queue improvements -+ private final Object lock = new Object(); // Paper - Chunk queue improvements - private static final Logger a = LogManager.getLogger(); - private Map b = new ConcurrentHashMap(); -- private Set c = Collections.newSetFromMap(new ConcurrentHashMap()); -+ //private Set c = Collections.newSetFromMap(new ConcurrentHashMap()); // Paper - Chunk queue improvements - private final File d; - private final DataConverterManager e; - private boolean f = false; -@@ -32,11 +35,11 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { - public boolean chunkExists(World world, int i, int j) { - ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(i, j); - -- if (this.c.contains(chunkcoordintpair)) { -+ //if (this.c.contains(chunkcoordintpair)) { // Paper - Chunk queue improvements - if (this.b.containsKey(chunkcoordintpair)) { - return true; - } -- } -+ //} // Paper - Chunk queue improvements - - // Paper start - Don't create region files when checking that they exist - final RegionFile region = RegionFileCache.a(this.d, i, j, false); -@@ -139,28 +142,32 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { - } - - protected void a(ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound) { -- if (!this.c.contains(chunkcoordintpair)) { -+ synchronized (lock) { // Paper - Chunk queue improvements - this.b.put(chunkcoordintpair, nbttagcompound); - } -+ queue.add(new QueuedChunk(chunkcoordintpair, nbttagcompound)); // Paper - Chunk queue improvements - - FileIOThread.a().a(this); - } - - public boolean c() { -- if (this.b.isEmpty()) { -+ // Paper start - Chunk queue improvements -+ QueuedChunk chunk = queue.poll(); -+ if (chunk == null) { -+ // Paper - end - if (this.f) { - ChunkRegionLoader.a.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", new Object[] { this.d.getName()}); - } - - return false; - } else { -- ChunkCoordIntPair chunkcoordintpair = (ChunkCoordIntPair) this.b.keySet().iterator().next(); -+ ChunkCoordIntPair chunkcoordintpair = chunk.coords; // Paper - Chunk queue improvements - - boolean flag; - - try { -- this.c.add(chunkcoordintpair); -- NBTTagCompound nbttagcompound = (NBTTagCompound) this.b.remove(chunkcoordintpair); -+ //this.c.add(chunkcoordintpair); -+ NBTTagCompound nbttagcompound = chunk.compound; // Paper - Chunk queue improvements - - if (nbttagcompound != null) { - try { -@@ -169,10 +176,11 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { - ChunkRegionLoader.a.error("Failed to save chunk", exception); - } - } -+ synchronized (lock) { if (this.b.get(chunkcoordintpair) == nbttagcompound) { this.b.remove(chunkcoordintpair); } }// Paper - This will not equal if a newer version is still pending - - flag = true; - } finally { -- this.c.remove(chunkcoordintpair); -+ //this.c.remove(chunkcoordintpair); // Paper - } - - return flag; -@@ -503,4 +511,16 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver { - return entity; - } - } -+ -+ // Paper start - Chunk queue improvements -+ private static class QueuedChunk { -+ public ChunkCoordIntPair coords; -+ public NBTTagCompound compound; -+ -+ public QueuedChunk(ChunkCoordIntPair coords, NBTTagCompound compound) { -+ this.coords = coords; -+ this.compound = compound; -+ } -+ } -+ // Paper end - } -diff --git a/src/main/java/net/minecraft/server/FileIOThread.java b/src/main/java/net/minecraft/server/FileIOThread.java -index 198b00f..d997dd4 100644 ---- a/src/main/java/net/minecraft/server/FileIOThread.java -+++ b/src/main/java/net/minecraft/server/FileIOThread.java -@@ -39,11 +39,15 @@ public class FileIOThread implements Runnable { - ++this.d; - } - -- try { -- Thread.sleep(this.e ? 0L : 10L); -- } catch (InterruptedException interruptedexception) { -- interruptedexception.printStackTrace(); -+ // Paper start - Add toggle -+ if (com.destroystokyo.paper.PaperConfig.enableFileIOThreadSleep) { -+ try { -+ Thread.sleep(this.e ? 0L : 10L); -+ } catch (InterruptedException interruptedexception) { -+ interruptedexception.printStackTrace(); -+ } - } -+ // Paper end - } - - if (this.b.isEmpty()) { --- -2.7.2 -