From 693102cce733bde3ec534acf3e3414b39014cfa6 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Sat, 22 Jun 2019 13:04:26 -0700 Subject: [PATCH] Fix performance regression in loadChunk(x, z, false) (#2211) Resolve a regression where calling loadChunk(x, z, false) would potentially double-load chunk data --- ...403-Fix-World-isChunkGenerated-calls.patch | 57 ++++++++++++++----- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/Spigot-Server-Patches/0403-Fix-World-isChunkGenerated-calls.patch b/Spigot-Server-Patches/0403-Fix-World-isChunkGenerated-calls.patch index d4f88edca0..9559cd62dc 100644 --- a/Spigot-Server-Patches/0403-Fix-World-isChunkGenerated-calls.patch +++ b/Spigot-Server-Patches/0403-Fix-World-isChunkGenerated-calls.patch @@ -1,4 +1,4 @@ -From 27e5668efea88ccb9b7f77a1d7222b6b9f2ac65a Mon Sep 17 00:00:00 2001 +From 23a4b689721fa3621f748f7f49390748eb82cf15 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Sat, 15 Jun 2019 08:54:33 -0700 Subject: [PATCH] Fix World#isChunkGenerated calls @@ -232,10 +232,23 @@ index 2e14d84657..d610253b95 100644 } diff --git a/src/main/java/net/minecraft/server/RegionFileCache.java b/src/main/java/net/minecraft/server/RegionFileCache.java -index 6f34d8aea0..d1323891fa 100644 +index 6f34d8aea0..d2b3289450 100644 --- a/src/main/java/net/minecraft/server/RegionFileCache.java +++ b/src/main/java/net/minecraft/server/RegionFileCache.java -@@ -110,6 +110,7 @@ public abstract class RegionFileCache implements AutoCloseable { +@@ -47,6 +47,12 @@ public abstract class RegionFileCache implements AutoCloseable { + // Paper start + } + ++ // Paper start ++ public RegionFile getRegionFileIfLoaded(ChunkCoordIntPair chunkcoordintpair) { ++ return this.cache.getAndMoveToFirst(ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ())); ++ } ++ // Paper end ++ + public RegionFile getRegionFile(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { return this.a(chunkcoordintpair, existingOnly); } // Paper - OBFHELPER + private RegionFile a(ChunkCoordIntPair chunkcoordintpair, boolean existingOnly) throws IOException { // CraftBukkit + long i = ChunkCoordIntPair.pair(chunkcoordintpair.getRegionX(), chunkcoordintpair.getRegionZ()); +@@ -110,6 +116,7 @@ public abstract class RegionFileCache implements AutoCloseable { try { NBTCompressedStreamTools.writeNBT(nbttagcompound, out); out.close(); @@ -243,7 +256,7 @@ index 6f34d8aea0..d1323891fa 100644 regionfile.setOversized(chunkX, chunkZ, false); } catch (RegionFile.ChunkTooLargeException ignored) { printOversizedLog("ChunkTooLarge! Someone is trying to duplicate.", regionfile.file, chunkX, chunkZ); -@@ -127,6 +128,7 @@ public abstract class RegionFileCache implements AutoCloseable { +@@ -127,6 +134,7 @@ public abstract class RegionFileCache implements AutoCloseable { if (SIZE_THRESHOLD == OVERZEALOUS_THRESHOLD) { resetFilterThresholds(); } @@ -252,7 +265,7 @@ index 6f34d8aea0..d1323891fa 100644 printOversizedLog("ChunkTooLarge even after reduction. Trying in overzealous mode.", regionfile.file, chunkX, chunkZ); // Eek, major fail. We have retry logic, so reduce threshholds and fall back diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index e0d89cc533..53d4f46d45 100644 +index e0d89cc533..9bb1ad077a 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -387,8 +387,20 @@ public class CraftWorld implements World { @@ -277,7 +290,7 @@ index e0d89cc533..53d4f46d45 100644 } catch (IOException ex) { throw new RuntimeException(ex); } -@@ -500,20 +512,14 @@ public class CraftWorld implements World { +@@ -500,20 +512,24 @@ public class CraftWorld implements World { @Override public boolean loadChunk(int x, int z, boolean generate) { org.spigotmc.AsyncCatcher.catchOp( "chunk load"); // Spigot @@ -288,13 +301,22 @@ index e0d89cc533..53d4f46d45 100644 - // We then cycle through again to get the full chunk immediately, rather than after the ticket addition - chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.FULL, true); - } -- ++ // Paper - Optimize this method ++ if (!generate) { ++ net.minecraft.server.RegionFile file = world.getChunkProvider().playerChunkMap.getRegionFileIfLoaded(new ChunkCoordIntPair(x, z)); ++ if (file != null && file.getStatusIfCached(x, z) != ChunkStatus.FULL) { ++ return false; ++ } + - if (chunk instanceof net.minecraft.server.Chunk) { - world.getChunkProvider().addTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 1, Unit.INSTANCE); - return true; -+ // Paper - Optimize this method -+ if (!generate && !isChunkGenerated(x, z)) { -+ return false; ++ IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.EMPTY, true); ++ if (!(chunk instanceof ProtoChunkExtension) && !(chunk instanceof net.minecraft.server.Chunk)) { ++ return false; ++ } ++ // fall through to load ++ // we do this so we do not re-read the chunk data on disk } - - return false; @@ -305,7 +327,7 @@ index e0d89cc533..53d4f46d45 100644 } @Override -@@ -2127,21 +2133,11 @@ public class CraftWorld implements World { +@@ -2127,21 +2143,20 @@ public class CraftWorld implements World { // Paper start private Chunk getChunkAtGen(int x, int z, boolean gen) { @@ -322,8 +344,17 @@ index e0d89cc533..53d4f46d45 100644 - if (chunk instanceof net.minecraft.server.Chunk) { - return ((net.minecraft.server.Chunk)chunk).bukkitChunk; + // Note: Copied from loadChunk() -+ if (!gen && !isChunkGenerated(x, z)) { -+ return null; ++ if (!gen) { ++ net.minecraft.server.RegionFile file = world.getChunkProvider().playerChunkMap.getRegionFileIfLoaded(new ChunkCoordIntPair(x, z)); ++ if (file != null && file.getStatusIfCached(x, z) != ChunkStatus.FULL) { ++ return null; ++ } ++ IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, ChunkStatus.EMPTY, true); ++ if (!(chunk instanceof ProtoChunkExtension) && !(chunk instanceof net.minecraft.server.Chunk)) { ++ return null; ++ } ++ // fall through to load ++ // we do this so we do not re-read the chunk data on disk } - - return null;