geforkt von Mirrors/Paper
b75eeca0e5
Run urgent as 2 so urgent light can run as 1 (light run at chunk -1 for loading purposes)
115 Zeilen
5.8 KiB
Diff
115 Zeilen
5.8 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
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/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
|
|
index e490866b3f4ac846c5988f5bc564e3902c3786d3..b8631019b36aedb7b54a1e8852b911029cbe9af0 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
|
|
@@ -56,6 +56,13 @@ public class PlayerChunk {
|
|
this.playersInChunkTickRange = this.chunkMap.playerChunkTickRangeMap.getObjectsInRange(key);
|
|
}
|
|
// Paper end - optimise isOutsideOfRange
|
|
+ // Paper start - optimize chunk status progression without jumping through thread pool
|
|
+ public boolean canAdvanceStatus() {
|
|
+ ChunkStatus status = getChunkHolderStatus();
|
|
+ IChunkAccess chunk = getAvailableChunkNow();
|
|
+ return chunk != null && (status == null || chunk.getChunkStatus().isAtLeastStatus(getNextStatus(status)));
|
|
+ }
|
|
+ // Paper end
|
|
|
|
// Paper start - no-tick view distance
|
|
public final Chunk getSendingChunk() {
|
|
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
index 302db2ca5149c30dec9fd39d1bf4fd23d53587c7..c5b5aaf4dd087dc87ecef08be4c8170f10e96b54 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
@@ -88,6 +88,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
public final WorldServer world;
|
|
private final LightEngineThreaded lightEngine;
|
|
private final IAsyncTaskHandler<Runnable> executor;
|
|
+ final java.util.concurrent.Executor mainInvokingExecutor; // Paper
|
|
public final ChunkGenerator<?> chunkGenerator;
|
|
private final Supplier<WorldPersistentData> l; public final Supplier<WorldPersistentData> getWorldPersistentDataSupplier() { return this.l; } // Paper - OBFHELPER
|
|
private final VillagePlace m;
|
|
@@ -285,6 +286,15 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
this.world = worldserver;
|
|
this.chunkGenerator = chunkgenerator;
|
|
this.executor = iasynctaskhandler;
|
|
+ // Paper start - optimize chunk status progression without jumping through thread pool
|
|
+ this.mainInvokingExecutor = (run) -> {
|
|
+ if (MCUtil.isMainThread()) {
|
|
+ run.run();
|
|
+ } else {
|
|
+ iasynctaskhandler.execute(run);
|
|
+ }
|
|
+ };
|
|
+ // Paper end
|
|
ThreadedMailbox<Runnable> threadedmailbox = ThreadedMailbox.a(executor, "worldgen");
|
|
|
|
iasynctaskhandler.getClass();
|
|
@@ -707,7 +717,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
return either.mapLeft((list) -> {
|
|
return (Chunk) list.get(list.size() / 2);
|
|
});
|
|
- }, this.executor);
|
|
+ }, this.mainInvokingExecutor); // Paper
|
|
}
|
|
|
|
@Nullable
|
|
@@ -1073,7 +1083,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
return this.b(playerchunk, chunkstatus);
|
|
}
|
|
}
|
|
- }, this.executor);
|
|
+ }, this.mainInvokingExecutor); // Paper - optimize chunk status progression without jumping through thread pool
|
|
}
|
|
}
|
|
|
|
@@ -1184,6 +1194,12 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
return CompletableFuture.completedFuture(Either.right(playerchunk_failure));
|
|
});
|
|
}, (runnable) -> {
|
|
+ // Paper start - optimize chunk status progression without jumping through thread pool
|
|
+ if (playerchunk.canAdvanceStatus()) {
|
|
+ this.mainInvokingExecutor.execute(runnable);
|
|
+ return;
|
|
+ }
|
|
+ // Paper end
|
|
this.mailboxWorldGen.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); // CraftBukkit - decompile error
|
|
});
|
|
}
|