mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-05 00:43:56 +01:00
74f507f4e3
Upstream has released updates that appears to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: e461dcfe #555: Item - add getters/setters for owner/thrower CraftBukkit Changes: 055870c4 #758: Item - add getters/setters for owner/thrower
100 lines
5.2 KiB
Diff
100 lines
5.2 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 ca9e0208aa35c597a947485f67213ff4b1b1185f..7de56172023e49cd8957e3dd45fa8e731809c16a 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
|
|
@@ -58,6 +58,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 b6ae589548bdc75052f4986069b3374cb5fd837c..c44eeaae0cff03ae5cfa53b3c0f240ef5e982083 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
@@ -741,7 +741,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
|
|
@@ -1091,7 +1091,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
IChunkAccess ichunkaccess = (IChunkAccess) optional.get();
|
|
|
|
if (ichunkaccess.getChunkStatus().b(chunkstatus)) {
|
|
- CompletableFuture completablefuture1;
|
|
+ CompletableFuture<Either<IChunkAccess, PlayerChunk.Failure>> completablefuture1; // Paper
|
|
|
|
if (chunkstatus == ChunkStatus.LIGHT) {
|
|
completablefuture1 = this.b(playerchunk, chunkstatus);
|
|
@@ -1107,7 +1107,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
return this.b(playerchunk, chunkstatus);
|
|
}
|
|
}
|
|
- }, this.executor);
|
|
+ }, this.mainInvokingExecutor).thenComposeAsync(CompletableFuture::completedFuture, this.mainInvokingExecutor); // Paper - optimize chunk status progression without jumping through thread pool - ensure main
|
|
}
|
|
}
|
|
|
|
@@ -1228,6 +1228,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));
|
|
});
|
|
}
|