From bb3f8a4aea7687f251a7b0ad7133c7a16c58d980 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Thu, 2 Mar 2023 23:31:59 -0800 Subject: [PATCH] Process player chunk loader mid tick at the start of tick Additionally, process ticket updates as well if either the mid tick logic did anything or whether we processed any chunk tasks. We process the mid tick logic at the start to be consistent with the inbetween task execution logic (which is not implemented), and we process ticket updates to ensure that any full status changes are processed from chunk tasks. --- patches/server/0004-Threaded-Regions.patch | 88 ++++++++++++++++--- ...lism-for-neighbour-writing-chunk-sta.patch | 8 +- 2 files changed, 82 insertions(+), 14 deletions(-) diff --git a/patches/server/0004-Threaded-Regions.patch b/patches/server/0004-Threaded-Regions.patch index b1d2acc..6d5754a 100644 --- a/patches/server/0004-Threaded-Regions.patch +++ b/patches/server/0004-Threaded-Regions.patch @@ -2133,10 +2133,10 @@ index 6df1948b1204a7288ecb7238b6fc2a733f7d25b3..6a413abc67aa4dcbab64231be3eb1344 public static ChunkHolder getUnloadingChunkHolder(final ServerLevel level, final int chunkX, final int chunkZ) { diff --git a/src/main/java/io/papermc/paper/chunk/system/RegionisedPlayerChunkLoader.java b/src/main/java/io/papermc/paper/chunk/system/RegionisedPlayerChunkLoader.java -index 7e2176f343160b299e7d4a2817c8f6c9ba7dba7b..245242b276e3de1edde1e2ebd0ce518fd0d08117 100644 +index 7e2176f343160b299e7d4a2817c8f6c9ba7dba7b..9d44c3923ba29d88e39b742f3da97372626b352e 100644 --- a/src/main/java/io/papermc/paper/chunk/system/RegionisedPlayerChunkLoader.java +++ b/src/main/java/io/papermc/paper/chunk/system/RegionisedPlayerChunkLoader.java -@@ -232,7 +232,7 @@ public class RegionisedPlayerChunkLoader { +@@ -232,17 +232,19 @@ public class RegionisedPlayerChunkLoader { public void tick() { TickThread.ensureTickThread("Cannot tick player chunk loader async"); long currTime = System.nanoTime(); @@ -2145,15 +2145,56 @@ index 7e2176f343160b299e7d4a2817c8f6c9ba7dba7b..245242b276e3de1edde1e2ebd0ce518f player.chunkLoader.update(); player.chunkLoader.midTickUpdate(currTime); } -@@ -240,7 +240,7 @@ public class RegionisedPlayerChunkLoader { + } - public void tickMidTick() { +- public void tickMidTick() { ++ public boolean tickMidTick() { // Folia - region threading - report whether tickets were added final long time = System.nanoTime(); - for (final ServerPlayer player : this.world.players()) { +- player.chunkLoader.midTickUpdate(time); ++ boolean ret = false; // Folia - region threading - report whether tickets were added + for (final ServerPlayer player : this.world.getLocalPlayers()) { // Folia - region threading - player.chunkLoader.midTickUpdate(time); ++ ret |= player.chunkLoader.midTickUpdate(time); } ++ return ret; // Folia - region threading - report whether tickets were added } + + private static long[] generateBFSOrder(final int radius) { +@@ -384,13 +386,13 @@ public class RegionisedPlayerChunkLoader { + this.player = player; + } + +- private void flushDelayedTicketOps() { ++ private boolean flushDelayedTicketOps() { // Folia - region threading - report whether tickets were added + if (this.delayedTicketOps.isEmpty()) { +- return; ++ return false; // Folia - region threading - report whether tickets were added + } + this.world.chunkTaskScheduler.chunkHolderManager.pushDelayedTicketUpdates(this.delayedTicketOps); + this.delayedTicketOps.clear(); +- this.world.chunkTaskScheduler.chunkHolderManager.tryDrainTicketUpdates(); ++ return this.world.chunkTaskScheduler.chunkHolderManager.tryDrainTicketUpdates() == Boolean.TRUE; // Folia - region threading - report whether tickets were added + } + + private void pushDelayedTicketOp(final ChunkHolderManager.TicketOperation op) { +@@ -607,7 +609,7 @@ public class RegionisedPlayerChunkLoader { + return Math.max(Math.abs(dx), Math.abs(dz)) <= this.lastTickDistance; + } + +- void midTickUpdate(final long time) { ++ boolean midTickUpdate(final long time) { // Folia - region threading - report whether tickets were added + TickThread.ensureTickThread(this.player, "Cannot tick player chunk loader async"); + // update rate limits + this.chunkSendCounter.update(time); +@@ -799,7 +801,7 @@ public class RegionisedPlayerChunkLoader { + this.chunkSendCounter.addTime(time, sendSlots); + } + +- this.flushDelayedTicketOps(); ++ return this.flushDelayedTicketOps(); // Folia - region threading - report whether tickets were added + // we assume propagate ticket levels happens after this call + } + diff --git a/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java b/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java index 61c170555c8854b102c640b0b6a615f9f732edbf..515cc130a411f218ed20628eb918be9d770b9939 100644 --- a/src/main/java/io/papermc/paper/chunk/system/entity/EntityLookup.java @@ -4508,10 +4549,10 @@ index 0000000000000000000000000000000000000000..269c051e20cd07e692c624a873e4ee2b +} diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionisedTaskQueue.java b/src/main/java/io/papermc/paper/threadedregions/RegionisedTaskQueue.java new file mode 100644 -index 0000000000000000000000000000000000000000..c13237edb7323fa747d260375f626a5c9979b004 +index 0000000000000000000000000000000000000000..a40b88fbee7b92de38b49c4dfa7c279665043a80 --- /dev/null +++ b/src/main/java/io/papermc/paper/threadedregions/RegionisedTaskQueue.java -@@ -0,0 +1,742 @@ +@@ -0,0 +1,754 @@ +package io.papermc.paper.threadedregions; + +import ca.spottedleaf.concurrentutil.collection.MultiThreadedQueue; @@ -4743,6 +4784,13 @@ index 0000000000000000000000000000000000000000..c13237edb7323fa747d260375f626a5c + } + + public void drainTasks() { ++ // first, update chunk loader ++ final ServerLevel world = this.worldRegionTaskData.world; ++ if (world.playerChunkLoader.tickMidTick()) { ++ // only process ticket updates if the player chunk loader did anything ++ world.chunkTaskScheduler.chunkHolderManager.processTicketUpdates(); ++ } ++ + final PrioritisedQueue tickTaskQueue = this.tickTaskQueue; + final PrioritisedQueue chunkTaskQueue = this.chunkQueue; + @@ -4758,6 +4806,11 @@ index 0000000000000000000000000000000000000000..c13237edb7323fa747d260375f626a5c + executeChunkTasks = executeChunkTasks && allowedChunkTasks-- > 0 && chunkTaskQueue.executeTask(); + executeGlobalTasks = executeGlobalTasks && this.worldRegionTaskData.executeGlobalChunkTask(); + } while (executeTickTasks | executeChunkTasks | executeGlobalTasks); ++ ++ if (allowedChunkTasks > 0) { ++ // if we executed chunk tasks, we should try to process ticket updates for full status changes ++ world.chunkTaskScheduler.chunkHolderManager.processTicketUpdates(); ++ } + } + + public boolean hasTasks() { @@ -8171,10 +8224,10 @@ index 0000000000000000000000000000000000000000..e75aac237764c7a9fa0538ddf8d68b1e +} diff --git a/src/main/java/io/papermc/paper/threadedregions/TickRegions.java b/src/main/java/io/papermc/paper/threadedregions/TickRegions.java new file mode 100644 -index 0000000000000000000000000000000000000000..c17669c1e98cd954643fa3b988c12b4b6c3b174e +index 0000000000000000000000000000000000000000..390bda127be9be5349c1c442ca01df6b56bfdfb9 --- /dev/null +++ b/src/main/java/io/papermc/paper/threadedregions/TickRegions.java -@@ -0,0 +1,340 @@ +@@ -0,0 +1,355 @@ +package io.papermc.paper.threadedregions; + +import ca.spottedleaf.concurrentutil.scheduler.SchedulerThreadPool; @@ -8496,6 +8549,16 @@ index 0000000000000000000000000000000000000000..c17669c1e98cd954643fa3b988c12b4b + @Override + protected boolean runRegionTasks(final BooleanSupplier canContinue) { + final RegionisedTaskQueue.RegionTaskQueueData queue = this.region.taskQueueData; ++ ++ // first, update chunk loader ++ final ServerLevel world = this.region.world; ++ if (world.playerChunkLoader.tickMidTick()) { ++ // only process ticket updates if the player chunk loader did anything ++ world.chunkTaskScheduler.chunkHolderManager.processTicketUpdates(); ++ } ++ ++ boolean processedChunkTask = false; ++ + boolean executeChunkTask = true; + boolean executeTickTask = true; + do { @@ -8503,9 +8566,14 @@ index 0000000000000000000000000000000000000000..c17669c1e98cd954643fa3b988c12b4b + executeTickTask = queue.executeTickTask(); + } + if (executeChunkTask) { -+ executeChunkTask = queue.executeChunkTask(); ++ processedChunkTask |= (executeChunkTask = queue.executeChunkTask()); + } + } while ((executeChunkTask | executeTickTask) && canContinue.getAsBoolean()); ++ ++ if (processedChunkTask) { ++ // if we processed any chunk tasks, try to process ticket level updates for full status changes ++ world.chunkTaskScheduler.chunkHolderManager.processTicketUpdates(); ++ } + return true; + } + diff --git a/patches/server/0005-Increase-parallelism-for-neighbour-writing-chunk-sta.patch b/patches/server/0005-Increase-parallelism-for-neighbour-writing-chunk-sta.patch index 8f642ce..f3288b9 100644 --- a/patches/server/0005-Increase-parallelism-for-neighbour-writing-chunk-sta.patch +++ b/patches/server/0005-Increase-parallelism-for-neighbour-writing-chunk-sta.patch @@ -10,7 +10,7 @@ will allow the chunk system to scale beyond 10 threads per world. diff --git a/src/main/java/io/papermc/paper/chunk/system/RegionisedPlayerChunkLoader.java b/src/main/java/io/papermc/paper/chunk/system/RegionisedPlayerChunkLoader.java -index 245242b276e3de1edde1e2ebd0ce518fd0d08117..acf77a7745db2e28bd674107cdcb65d278625445 100644 +index 9d44c3923ba29d88e39b742f3da97372626b352e..9522cdbe432f973532569d225327e4f4e1d68edd 100644 --- a/src/main/java/io/papermc/paper/chunk/system/RegionisedPlayerChunkLoader.java +++ b/src/main/java/io/papermc/paper/chunk/system/RegionisedPlayerChunkLoader.java @@ -12,6 +12,7 @@ import it.unimi.dsi.fastutil.longs.LongArrayFIFOQueue; @@ -32,7 +32,7 @@ index 245242b276e3de1edde1e2ebd0ce518fd0d08117..acf77a7745db2e28bd674107cdcb65d2 import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; -@@ -286,7 +288,92 @@ public class RegionisedPlayerChunkLoader { +@@ -288,7 +290,92 @@ public class RegionisedPlayerChunkLoader { } } @@ -196,7 +196,7 @@ index 0b7a2b0ead4f3bc07bfd9a38c2b7cf024bd140c6..36e93fefdfbebddce4c153974c7cd81a final int chunkX = CoordinateUtils.getChunkX(coordinate); final int chunkZ = CoordinateUtils.getChunkZ(coordinate); diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java -index 32b88d7902e877e1cce0b7635cbfa67b84b8eac0..89e8b5d3a62241df0e3cb5c296f1deb754305843 100644 +index 32b88d7902e877e1cce0b7635cbfa67b84b8eac0..e787c54b8f4be6923370a704d1c414f5f3274bae 100644 --- a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java +++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java @@ -1306,17 +1306,23 @@ public final class ChunkHolderManager { @@ -213,7 +213,7 @@ index 32b88d7902e877e1cce0b7635cbfa67b84b8eac0..89e8b5d3a62241df0e3cb5c296f1deb7 + final boolean acquired = this.ticketLock.tryLock(); + try { + if (!acquired) { -+ return null; ++ return ret ? Boolean.TRUE : null; + } - return Boolean.valueOf(this.drainTicketUpdates());