aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0492-Improve-Chunk-Status-Transition-Speed.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/server/0492-Improve-Chunk-Status-Transition-Speed.patch')
-rw-r--r--patches/server/0492-Improve-Chunk-Status-Transition-Speed.patch81
1 files changed, 81 insertions, 0 deletions
diff --git a/patches/server/0492-Improve-Chunk-Status-Transition-Speed.patch b/patches/server/0492-Improve-Chunk-Status-Transition-Speed.patch
new file mode 100644
index 0000000000..e3f37a7db6
--- /dev/null
+++ b/patches/server/0492-Improve-Chunk-Status-Transition-Speed.patch
@@ -0,0 +1,81 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Aikar <[email protected]>
+Date: Fri, 29 May 2020 23:32:14 -0400
+Subject: [PATCH] Improve Chunk Status Transition Speed
+
+When a chunk is loaded from disk that has already been generated,
+the server has to promote the chunk through the system to reach
+it's current desired status level.
+
+This results in every single status transition going from the main thread
+to the world gen threads, only to discover it has no work it actually
+needs to do.... and then it returns back to main.
+
+This back and forth costs a lot of time and can really delay chunk loads
+when the server is under high TPS due to their being a lot of time in
+between chunk load times, as well as hogs up the chunk threads from doing
+actual generation and light work.
+
+Additionally, the whole task system uses a lot of CPU on the server threads anyways.
+
+So by optimizing status transitions for status's that are already complete,
+we can run them to the desired level while on main thread (where it has
+to happen anyways) instead of ever jumping to world gen thread.
+
+This will improve chunk loading effeciency to be reduced down to the following
+scenario / path:
+
+1) MAIN: Chunk Requested, Load Request sent to ChunkTaskManager / IO Queue
+2) IO: Once position in queue comes, submit read IO data and schedule to chunk task thread
+3) CHUNK: Once IO is loaded and position in queue comes, deserialize the chunk data, process conversions, submit to main queue
+4) MAIN: next Chunk Task process (Mid Tick or End Of Tick), load chunk data into world (POI, main thread tasks)
+5) MAIN: process status transitions all the way to LIGHT, light schedules Threaded task
+6) SERVER: Light tasks register light enablement for chunk and any lighting needing to be done
+7) MAIN: Task returns to main, finish processing to FULL/TICKING status
+
+Previously would have hopped to SERVER around 12+ times there extra.
+
+diff --git a/src/main/java/net/minecraft/server/level/ChunkHolder.java b/src/main/java/net/minecraft/server/level/ChunkHolder.java
+index 87271552aa85626f22f7f8569c8fb48fe4b30bf3..80aae4303e011dad13ce818136f0383e12ab5c41 100644
+--- a/src/main/java/net/minecraft/server/level/ChunkHolder.java
++++ b/src/main/java/net/minecraft/server/level/ChunkHolder.java
+@@ -87,6 +87,13 @@ public class ChunkHolder {
+ // Paper end - optimise anyPlayerCloseEnoughForSpawning
+ long lastAutoSaveTime; // Paper - incremental autosave
+ long inactiveTimeStart; // Paper - incremental autosave
++ // Paper start - optimize chunk status progression without jumping through thread pool
++ public boolean canAdvanceStatus() {
++ ChunkStatus status = getChunkHolderStatus();
++ ChunkAccess chunk = getAvailableChunkNow();
++ return chunk != null && (status == null || chunk.getStatus().isOrAfter(getNextStatus(status)));
++ }
++ // Paper end
+
+ public ChunkHolder(ChunkPos pos, int level, LevelHeightAccessor world, LevelLightEngine lightingProvider, ChunkHolder.LevelChangeListener levelUpdateListener, ChunkHolder.PlayerProvider playersWatchingChunkProvider) {
+ this.futures = new AtomicReferenceArray(ChunkHolder.CHUNK_STATUSES.size());
+diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
+index 0b8b813d329aa1de912057ddeb52c0442f262f13..a97bf06a0e8ba1cd612f7e8be2585bfdfbdfa969 100644
+--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
+@@ -636,7 +636,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+ return either.mapLeft((list) -> {
+ return (LevelChunk) list.get(list.size() / 2);
+ });
+- }, this.mainThreadExecutor);
++ }, this.mainInvokingExecutor); // Paper
+ }
+
+ @Nullable
+@@ -1046,6 +1046,12 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+ return "chunkGenerate " + requiredStatus.getName();
+ });
+ Executor executor = (runnable) -> {
++ // Paper start - optimize chunk status progression without jumping through thread pool
++ if (holder.canAdvanceStatus()) {
++ this.mainInvokingExecutor.execute(runnable);
++ return;
++ }
++ // Paper end
+ this.worldgenMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable));
+ };
+