geforkt von Mirrors/Paper
Further improve Chunk Light Prioritization
This is as fast as its going to get outside of making the light engine calculations it self faster. Fixes #4022
Dieser Commit ist enthalten in:
Ursprung
0d19e4579b
Commit
960d992fd2
@ -1027,10 +1027,10 @@ 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..97c41fa1306798dad08ad9797c61f13d0dff6f52 100644
|
||||
index a9dc8466278f9ec2becbcb643e6e1c973df72b82..1e70754529847e077f88af01c087aba6a887c039 100644
|
||||
--- a/src/main/java/net/minecraft/server/LightEngineThreaded.java
|
||||
+++ b/src/main/java/net/minecraft/server/LightEngineThreaded.java
|
||||
@@ -15,15 +15,119 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
|
||||
@@ -15,15 +15,153 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private final ThreadedMailbox<Runnable> b;
|
||||
@ -1038,20 +1038,6 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..97c41fa1306798dad08ad9797c61f13d
|
||||
- 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.priorityChanges.add(() -> {
|
||||
+ ChunkLightQueue remove = this.queue.buckets[currentPriority].remove(pair);
|
||||
+ if (remove != null) {
|
||||
+ ChunkLightQueue existing = this.queue.buckets[priority].put(pair, remove);
|
||||
+ if (existing != null) {
|
||||
+ remove.pre.addAll(existing.pre);
|
||||
+ remove.post.addAll(existing.post);
|
||||
+ }
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ private boolean isChunkLightStatus(long pair) {
|
||||
+ PlayerChunk playerChunk = playerChunkMap.getUpdatingChunk(pair);
|
||||
@ -1070,12 +1056,28 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..97c41fa1306798dad08ad9797c61f13d
|
||||
+ ChunkLightQueue(long chunk) {}
|
||||
+ }
|
||||
+
|
||||
+ static class PendingChunkLight {
|
||||
+ long chunkId;
|
||||
+ int priority;
|
||||
+ Runnable pre;
|
||||
+ Runnable post;
|
||||
+
|
||||
+ public PendingChunkLight(long chunkId, int priority, Runnable pre, Runnable post) {
|
||||
+ this.chunkId = chunkId;
|
||||
+ this.priority = priority;
|
||||
+ this.pre = pre;
|
||||
+ this.post = post;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ // Retain the chunks priority level for queued light tasks
|
||||
+ private class LightQueue {
|
||||
+ 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];
|
||||
+ private final java.util.concurrent.ConcurrentLinkedQueue<PendingChunkLight> pendingChunks = new java.util.concurrent.ConcurrentLinkedQueue<>();
|
||||
+ private final java.util.concurrent.ConcurrentLinkedQueue<Runnable> priorityChanges = new java.util.concurrent.ConcurrentLinkedQueue<>();
|
||||
+
|
||||
+ private LightQueue() {
|
||||
+ for (int i = 0; i < buckets.length; i++) {
|
||||
@ -1083,6 +1085,29 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..97c41fa1306798dad08ad9797c61f13d
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void changePriority(long pair, int currentPriority, int priority) {
|
||||
+ this.priorityChanges.add(() -> {
|
||||
+ ChunkLightQueue remove = this.buckets[currentPriority].remove(pair);
|
||||
+ if (remove != null) {
|
||||
+ ChunkLightQueue existing = this.buckets[priority].put(pair, remove);
|
||||
+ if (existing != null) {
|
||||
+ remove.pre.addAll(existing.pre);
|
||||
+ remove.post.addAll(existing.post);
|
||||
+ }
|
||||
+ }
|
||||
+ if (this.buckets[priority].containsKey(pair)) {
|
||||
+ if (lowestPriority > priority) {
|
||||
+ lowestPriority = priority;
|
||||
+ }
|
||||
+ }
|
||||
+ });
|
||||
+ }
|
||||
+
|
||||
+ public final void addChunk(long chunkId, int priority, Runnable pre, Runnable post) {
|
||||
+ pendingChunks.add(new PendingChunkLight(chunkId, priority, pre, post));
|
||||
+ queueUpdate();
|
||||
+ }
|
||||
+
|
||||
+ public final void add(long chunkId, int priority, LightEngineThreaded.Update type, Runnable run) {
|
||||
+ add(chunkId, priority, type, run, false);
|
||||
+ }
|
||||
@ -1104,7 +1129,7 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..97c41fa1306798dad08ad9797c61f13d
|
||||
+ }
|
||||
+
|
||||
+ public final boolean isEmpty() {
|
||||
+ return this.size == 0;
|
||||
+ return this.size == 0 && this.pendingChunks.isEmpty();
|
||||
+ }
|
||||
+
|
||||
+ public final int size() {
|
||||
@ -1112,6 +1137,11 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..97c41fa1306798dad08ad9797c61f13d
|
||||
+ }
|
||||
+
|
||||
+ public boolean poll(java.util.List<Runnable> pre, java.util.List<Runnable> post) {
|
||||
+ PendingChunkLight chunk;
|
||||
+ while ((chunk = pendingChunks.poll()) != null) {
|
||||
+ add(chunk.chunkId, chunk.priority, Update.PRE_UPDATE, chunk.pre, true);
|
||||
+ add(chunk.chunkId, chunk.priority, Update.POST_UPDATE, chunk.post, true);
|
||||
+ }
|
||||
+ Runnable run;
|
||||
+ while ((run = priorityChanges.poll()) != null) {
|
||||
+ run.run();
|
||||
@ -1122,7 +1152,11 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..97c41fa1306798dad08ad9797c61f13d
|
||||
+ it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap<ChunkLightQueue> bucket = buckets[lowestPriority];
|
||||
+ if (bucket.isEmpty()) {
|
||||
+ lowestPriority++;
|
||||
+ continue;
|
||||
+ if (hasWork && lowestPriority <= 3) {
|
||||
+ return true;
|
||||
+ } else {
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+ ChunkLightQueue queue = bucket.removeFirst();
|
||||
+ this.size -= queue.pre.size() + queue.post.size();
|
||||
@ -1139,7 +1173,7 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..97c41fa1306798dad08ad9797c61f13d
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private final LightQueue queue = new LightQueue();
|
||||
+ final LightQueue queue = new LightQueue();
|
||||
+ // Paper end
|
||||
+ private final PlayerChunkMap d; private final PlayerChunkMap playerChunkMap; // Paper
|
||||
private final Mailbox<ChunkTaskQueueSorter.a<Runnable>> e;
|
||||
@ -1153,7 +1187,7 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..97c41fa1306798dad08ad9797c61f13d
|
||||
this.e = mailbox;
|
||||
this.b = threadedmailbox;
|
||||
}
|
||||
@@ -111,10 +215,10 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
|
||||
@@ -111,10 +249,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(() -> {
|
||||
@ -1168,7 +1202,7 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..97c41fa1306798dad08ad9797c61f13d
|
||||
|
||||
}, ChunkCoordIntPair.pair(i, j), intsupplier));
|
||||
}
|
||||
@@ -133,8 +237,27 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
|
||||
@@ -133,8 +271,21 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
|
||||
public CompletableFuture<IChunkAccess> a(IChunkAccess ichunkaccess, boolean flag) {
|
||||
ChunkCoordIntPair chunkcoordintpair = ichunkaccess.getPos();
|
||||
|
||||
@ -1179,26 +1213,20 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..97c41fa1306798dad08ad9797c61f13d
|
||||
+ long pair = chunkcoordintpair.pair();
|
||||
+ CompletableFuture<IChunkAccess> future = new CompletableFuture<>();
|
||||
+ IntSupplier prioritySupplier = playerChunkMap.getPrioritySupplier(pair);
|
||||
+ this.e.a(ChunkTaskQueueSorter.a(() -> {
|
||||
+ // Chunk's no longer needed
|
||||
+ boolean[] skippedPre = {false};
|
||||
+ int priority = prioritySupplier.getAsInt();
|
||||
+ this.queue.addChunk(pair, priority, 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;
|
||||
+ }
|
||||
+ 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
|
||||
+ // Paper end
|
||||
ChunkSection[] achunksection = ichunkaccess.getSections();
|
||||
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
@@ -152,55 +275,55 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
|
||||
@@ -152,55 +303,47 @@ public class LightEngineThreaded extends LightEngine implements AutoCloseable {
|
||||
});
|
||||
}
|
||||
|
||||
@ -1206,11 +1234,10 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..97c41fa1306798dad08ad9797c61f13d
|
||||
+ this.d.c(chunkcoordintpair); // Paper - if change, copy into !isChunkLightStatus above
|
||||
}, () -> {
|
||||
return "lightChunk " + chunkcoordintpair + " " + flag;
|
||||
+ // Paper start - merge the 2 together
|
||||
}));
|
||||
- }));
|
||||
- return CompletableFuture.supplyAsync(() -> {
|
||||
+
|
||||
+ this.queue.add(pair, prioritySupplier.getAsInt(), LightEngineThreaded.Update.POST_UPDATE, () -> {
|
||||
+ // Paper start - merge the 2 together
|
||||
+ }), () -> {
|
||||
+ if (skippedPre[0]) return; // Paper - future's already complete
|
||||
ichunkaccess.b(true);
|
||||
super.b(chunkcoordintpair, false);
|
||||
@ -1220,8 +1247,6 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..97c41fa1306798dad08ad9797c61f13d
|
||||
+ // Paper start
|
||||
+ future.complete(ichunkaccess);
|
||||
});
|
||||
+ queueUpdate(); // run queue now
|
||||
+ }, pair, prioritySupplier));
|
||||
+ return future;
|
||||
+ // Paper end
|
||||
}
|
||||
@ -1253,15 +1278,15 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..97c41fa1306798dad08ad9797c61f13d
|
||||
- if (pair.getFirst() == LightEngineThreaded.Update.PRE_UPDATE) {
|
||||
- ((Runnable) pair.getSecond()).run();
|
||||
- }
|
||||
+ int i = Math.min(queue.size(), 4);
|
||||
+ boolean ran = false;
|
||||
+ while (i-- > 0 && queue.poll(pre, post)) {
|
||||
+ if (queue.poll(pre, post)) {
|
||||
+ pre.forEach(Runnable::run);
|
||||
+ pre.clear();
|
||||
+ super.a(Integer.MAX_VALUE, true, true);
|
||||
+ post.forEach(Runnable::run);
|
||||
+ post.clear();
|
||||
+ ran = true;
|
||||
+ } else {
|
||||
+ // might have level updates to go still
|
||||
+ super.a(Integer.MAX_VALUE, true, true);
|
||||
}
|
||||
-
|
||||
- objectlistiterator.back(j);
|
||||
@ -1274,10 +1299,7 @@ index a9dc8466278f9ec2becbcb643e6e1c973df72b82..97c41fa1306798dad08ad9797c61f13d
|
||||
- }
|
||||
-
|
||||
- objectlistiterator.remove();
|
||||
+ if (!ran) {
|
||||
+ // might have level updates to go still
|
||||
+ super.a(Integer.MAX_VALUE, true, true);
|
||||
}
|
||||
- }
|
||||
-
|
||||
+ // Paper end
|
||||
}
|
||||
@ -1302,14 +1324,14 @@ index 8cedfdd820cc02a76607b53e0b054fc74654f907..a9795394c9b17f9f0ce4c4f9c8f51a48
|
||||
private static final int nibbleBucketSizeMultiplier = Integer.getInteger("Paper.nibbleBucketSize", 3072);
|
||||
private static final int maxPoolSize = Integer.getInteger("Paper.maxNibblePoolSize", (int) Math.min(6, Math.max(1, Runtime.getRuntime().maxMemory() / 1024 / 1024 / 1024)) * (nibbleBucketSizeMultiplier * 8));
|
||||
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
index 446c401b3139f8c6c0e70d883340f0140d94b752..a3bce8f13bf278af2d6870891daa9bf692b4e267 100644
|
||||
index 446c401b3139f8c6c0e70d883340f0140d94b752..c14cdb60243e16810ad711d204678d51120c3403 100644
|
||||
--- a/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java
|
||||
@@ -716,6 +716,7 @@ public class PlayerChunk {
|
||||
ioPriority = com.destroystokyo.paper.io.PrioritizedTaskQueue.HIGH_PRIORITY;
|
||||
}
|
||||
chunkMap.world.asyncChunkTaskManager.raisePriority(location.x, location.z, ioPriority);
|
||||
+ chunkMap.world.getChunkProvider().getLightEngine().changePriority(location.pair(), getCurrentPriority(), priority);
|
||||
+ chunkMap.world.getChunkProvider().getLightEngine().queue.changePriority(location.pair(), getCurrentPriority(), priority);
|
||||
}
|
||||
if (getCurrentPriority() != priority) {
|
||||
this.v.a(this.location, this::getCurrentPriority, priority, this::setPriority); // use preferred priority
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren