Mirror von
https://github.com/PaperMC/Paper.git
synchronisiert 2024-12-16 03:20:07 +01:00
Fix Light Prioritization Issues
Ensures light priorities are properly processed before processing new work, skipping the threads queue. also stops processing work on task submission. Also drops dead chunks light work to not waste time on work thats going to be discarded. Fixes #3986 Fixes #4002 Fixes #3951
Dieser Commit ist enthalten in:
Ursprung
2d66b5be82
Commit
76728529f9
@ -1027,21 +1027,21 @@ index a35e7b392c74fadf2760d1fc2021e98d33858cb5..944094e8e770cc8c0205ef2aa6c48fff
|
||||
lightenginelayer.a(Long.MAX_VALUE, l3, 15, false);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/server/LightEngineThreaded.java b/src/main/java/net/minecraft/server/LightEngineThreaded.java
|
||||
index a9dc8466278f9ec2becbcb643e6e1c973df72b82..721f86a5405c9575d8ee3fc661395e65487b6d96 100644
|
||||
index a9dc8466278f9ec2becbcb643e6e1c973df72b82..97c41fa1306798dad08ad9797c61f13d0dff6f52 100644
|
||||
--- a/src/main/java/net/minecraft/server/LightEngineThreaded.java
|
||||
+++ b/src/main/java/net/minecraft/server/LightEngineThreaded.java
|
||||
@@ -14,8 +14,98 @@ import org.apache.logging.log4j.Logger;
|
||||
public class LightEngineThreaded extends LightEngine implements AutoCloseable {
|
||||
@@ -15,15 +15,119 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
- private final ThreadedMailbox<Runnable> b;
|
||||
private final ThreadedMailbox<Runnable> b;
|
||||
- private final ObjectList<Pair<LightEngineThreaded.Update, Runnable>> c = new ObjectArrayList();
|
||||
+ private final ThreadedMailbox<Runnable> b; ThreadedMailbox<Runnable> mailbox; // Paper
|
||||
- private final PlayerChunkMap d;
|
||||
+ // Paper start
|
||||
+ private static final int MAX_PRIORITIES = PlayerChunkMap.GOLDEN_TICKET + 2;
|
||||
+ private final java.util.concurrent.ConcurrentLinkedQueue<Runnable> priorityChanges = new java.util.concurrent.ConcurrentLinkedQueue<>();
|
||||
+
|
||||
+ public void changePriority(long pair, int currentPriority, int priority) {
|
||||
+ this.mailbox.queue(() -> {
|
||||
+ this.priorityChanges.add(() -> {
|
||||
+ ChunkLightQueue remove = this.queue.buckets[currentPriority].remove(pair);
|
||||
+ if (remove != null) {
|
||||
+ ChunkLightQueue existing = this.queue.buckets[priority].put(pair, remove);
|
||||
@ -1053,6 +1053,15 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..721f86a5405c9575d8ee3fc661395e65
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ private boolean isChunkLightStatus(long pair) {
|
||||
+ PlayerChunk playerChunk = playerChunkMap.getUpdatingChunk(pair);
|
||||
+ if (playerChunk == null) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ ChunkStatus status = PlayerChunk.getChunkStatus(playerChunk.getTicketLevel());
|
||||
+ return status != null && status.isAtLeastStatus(ChunkStatus.LIGHT);
|
||||
+ }
|
||||
+
|
||||
+ static class ChunkLightQueue {
|
||||
+ public boolean shouldFastUpdate;
|
||||
+ java.util.ArrayDeque<Runnable> pre = new java.util.ArrayDeque<Runnable>();
|
||||
@ -1063,7 +1072,7 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..721f86a5405c9575d8ee3fc661395e65
|
||||
+
|
||||
+
|
||||
+ // Retain the chunks priority level for queued light tasks
|
||||
+ private static class LightQueue {
|
||||
+ private class LightQueue {
|
||||
+ private int size = 0;
|
||||
+ private int lowestPriority = MAX_PRIORITIES;
|
||||
+ private final it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap<ChunkLightQueue>[] buckets = new it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap[MAX_PRIORITIES];
|
||||
@ -1103,6 +1112,10 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..721f86a5405c9575d8ee3fc661395e65
|
||||
+ }
|
||||
+
|
||||
+ public boolean poll(java.util.List<Runnable> pre, java.util.List<Runnable> post) {
|
||||
+ Runnable run;
|
||||
+ while ((run = priorityChanges.poll()) != null) {
|
||||
+ run.run();
|
||||
+ }
|
||||
+ boolean hasWork = false;
|
||||
+ it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap<ChunkLightQueue>[] buckets = this.buckets;
|
||||
+ while (lowestPriority < MAX_PRIORITIES && !isEmpty()) {
|
||||
@ -1128,49 +1141,69 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..721f86a5405c9575d8ee3fc661395e65
|
||||
+
|
||||
+ private final LightQueue queue = new LightQueue();
|
||||
+ // Paper end
|
||||
private final PlayerChunkMap d;
|
||||
+ private final PlayerChunkMap d; private final PlayerChunkMap playerChunkMap; // Paper
|
||||
private final Mailbox<ChunkTaskQueueSorter.a<Runnable>> e;
|
||||
private volatile int f = 5;
|
||||
@@ -25,7 +115,7 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
|
||||
super(ilightaccess, true, flag);
|
||||
this.d = playerchunkmap;
|
||||
this.e = mailbox;
|
||||
- this.b = threadedmailbox;
|
||||
+ this.mailbox = this.b = threadedmailbox; // Paper
|
||||
}
|
||||
private final AtomicBoolean g = new AtomicBoolean();
|
||||
|
||||
public void close() {}
|
||||
@@ -111,8 +201,11 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
|
||||
public LightEngineThreaded(ILightAccess ilightaccess, PlayerChunkMap playerchunkmap, boolean flag, ThreadedMailbox<Runnable> threadedmailbox, Mailbox<ChunkTaskQueueSorter.a<Runnable>> mailbox) {
|
||||
super(ilightaccess, true, flag);
|
||||
- this.d = playerchunkmap;
|
||||
+ this.d = playerchunkmap; this.playerChunkMap = d; // Paper
|
||||
this.e = mailbox;
|
||||
this.b = threadedmailbox;
|
||||
}
|
||||
@@ -111,10 +215,10 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
|
||||
|
||||
private void a(int i, int j, IntSupplier intsupplier, LightEngineThreaded.Update lightenginethreaded_update, Runnable runnable) {
|
||||
this.e.a(ChunkTaskQueueSorter.a(() -> {
|
||||
- this.c.add(Pair.of(lightenginethreaded_update, runnable));
|
||||
- if (this.c.size() >= this.f) {
|
||||
- this.b();
|
||||
- }
|
||||
+ // Paper start
|
||||
+ int priority = intsupplier.getAsInt();
|
||||
+ this.queue.add(ChunkCoordIntPair.pair(i, j), priority, lightenginethreaded_update, runnable); // Paper
|
||||
+ if (priority <= 25) { // don't auto kick off unless priority
|
||||
+ // Paper end
|
||||
this.b();
|
||||
}
|
||||
+ this.queue.add(ChunkCoordIntPair.pair(i, j), priority, lightenginethreaded_update, runnable);
|
||||
+ // Paper end
|
||||
|
||||
@@ -134,7 +227,13 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
|
||||
}, ChunkCoordIntPair.pair(i, j), intsupplier));
|
||||
}
|
||||
@@ -133,8 +237,27 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
|
||||
public CompletableFuture<IChunkAccess> a(IChunkAccess ichunkaccess, boolean flag) {
|
||||
ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos();
|
||||
|
||||
ichunkaccess.b(false);
|
||||
- ichunkaccess.b(false);
|
||||
- this.a(chunkcoordintpair.x, chunkcoordintpair.z, LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> {
|
||||
+ // Paper start
|
||||
+ //ichunkaccess.b(false); // Don't need to disable this
|
||||
+ long pair = chunkcoordintpair.pair();
|
||||
+ CompletableFuture<IChunkAccess> future = new CompletableFuture<>();
|
||||
+ IntSupplier prioritySupplier = d.getPrioritySupplier(pair);
|
||||
+ IntSupplier prioritySupplier = playerChunkMap.getPrioritySupplier(pair);
|
||||
+ this.e.a(ChunkTaskQueueSorter.a(() -> {
|
||||
+ // Chunk's no longer needed
|
||||
+ if (!isChunkLightStatus(pair)) {
|
||||
+ this.d.c(chunkcoordintpair); // copied from end of method to release light ticket
|
||||
+ future.complete(ichunkaccess);
|
||||
+ return;
|
||||
+ }
|
||||
+ boolean[] skippedPre = {false};
|
||||
+ this.queue.add(pair, prioritySupplier.getAsInt(), LightEngineThreaded.Update.PRE_UPDATE, SystemUtils.a(() -> {
|
||||
+ if (!isChunkLightStatus(pair)) {
|
||||
+ this.d.c(chunkcoordintpair); // copied from end of method to release light ticket
|
||||
+ future.complete(ichunkaccess);
|
||||
+ skippedPre[0] = true;
|
||||
+ return;
|
||||
+ }
|
||||
+ // Paper end
|
||||
ChunkSection[] achunksection = ichunkaccess.getSections();
|
||||
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
@@ -155,52 +254,51 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
|
||||
this.d.c(chunkcoordintpair);
|
||||
@@ -152,55 +275,55 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
|
||||
});
|
||||
}
|
||||
|
||||
- this.d.c(chunkcoordintpair);
|
||||
+ this.d.c(chunkcoordintpair); // Paper - if change, copy into !isChunkLightStatus above
|
||||
}, () -> {
|
||||
return "lightChunk " + chunkcoordintpair + " " + flag;
|
||||
+ // Paper start - merge the 2 together
|
||||
@ -1178,6 +1211,7 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..721f86a5405c9575d8ee3fc661395e65
|
||||
- return CompletableFuture.supplyAsync(() -> {
|
||||
+
|
||||
+ this.queue.add(pair, prioritySupplier.getAsInt(), LightEngineThreaded.Update.POST_UPDATE, () -> {
|
||||
+ if (skippedPre[0]) return; // Paper - future's already complete
|
||||
ichunkaccess.b(true);
|
||||
super.b(chunkcoordintpair, false);
|
||||
- return ichunkaccess;
|
||||
@ -1280,7 +1314,7 @@ index 446c401b3139f8c6c0e70d883340f0140d94b752..a3bce8f13bf278af2d6870891daa9bf6
|
||||
if (getCurrentPriority() != priority) {
|
||||
this.v.a(this.location, this::getCurrentPriority, priority, this::setPriority); // use preferred priority
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
index 2fac2e59ab0712459f03cdacc0f67c1528c5a5bf..5544254a655485b8ef9d2883da4d722fa57c63d9 100644
|
||||
index fea219dcfd5a98fc0e48fd70dc7d0fd41b2fc970..ad8a00e0fb5da5df1eb3afbf9ea50acfc89a5ff1 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
||||
@@ -653,6 +653,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren