Update Optimise chunk tick iteration (#6950)
This commit is contained in:
parent
c3ff7e0ff7
commit
fd4f6c5e31
5 changed files with 111 additions and 108 deletions
|
@ -1,94 +0,0 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <spottedleaf@spottedleaf.dev>
|
||||
Date: Thu, 7 May 2020 05:48:54 -0700
|
||||
Subject: [PATCH] Optimise chunk tick iteration
|
||||
|
||||
Use a dedicated list of entity ticking chunks to reduce the cost
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index b5c8f3f57d09de4caffeb9f3e20e9bf4daba1cdd..d6981bbcf480c5856b51960013d144beba2361b3 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -1007,19 +1007,35 @@ public class ServerChunkCache extends ChunkSource {
|
||||
|
||||
this.lastSpawnState = spawnercreature_d;
|
||||
this.level.getProfiler().pop();
|
||||
- List<ChunkHolder> list = Lists.newArrayList(this.chunkMap.getChunks());
|
||||
-
|
||||
- Collections.shuffle(list);
|
||||
+ // Paper - moved down, enabled if per-player = false
|
||||
// Paper - moved natural spawn event up
|
||||
this.level.timings.chunkTicks.startTiming(); // Paper
|
||||
- list.forEach((playerchunk) -> {
|
||||
- Optional<LevelChunk> optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left();
|
||||
-
|
||||
- if (optional.isPresent()) {
|
||||
- LevelChunk chunk = (LevelChunk) optional.get();
|
||||
+ // Paper start
|
||||
+ java.util.Iterator<LevelChunk> iterator;
|
||||
+ if (this.level.paperConfig.perPlayerMobSpawns) {
|
||||
+ iterator = this.entityTickingChunks.iterator();
|
||||
+ } else {
|
||||
+ iterator = this.entityTickingChunks.unsafeIterator();
|
||||
+ List<LevelChunk> shuffled = new java.util.ArrayList<>(this.entityTickingChunks.size());
|
||||
+ while (iterator.hasNext()) {
|
||||
+ shuffled.add(iterator.next());
|
||||
+ }
|
||||
+ Collections.shuffle(shuffled);
|
||||
+ iterator = shuffled.iterator();
|
||||
+ }
|
||||
+ try { while (iterator.hasNext()) {
|
||||
+ LevelChunk chunk = iterator.next();
|
||||
+ ChunkHolder playerchunk = chunk.playerChunk;
|
||||
+ if (playerchunk != null) {
|
||||
+ this.level.getProfiler().push("broadcast");
|
||||
+ this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timings
|
||||
+ playerchunk.broadcastChanges(chunk);
|
||||
+ this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timings
|
||||
+ this.level.getProfiler().pop();
|
||||
+ // Paper end
|
||||
ChunkPos chunkcoordintpair = chunk.getPos();
|
||||
|
||||
- if (this.level.isPositionEntityTicking(chunkcoordintpair) && !this.chunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, false)) { // Paper - optimise isOutsideOfRange
|
||||
+ if ((true || this.level.isPositionEntityTicking(chunkcoordintpair)) && !this.chunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, false)) { // Paper - optimise isOutsideOfRange // Paper - we only iterate entity ticking chunks
|
||||
chunk.setInhabitedTime(chunk.getInhabitedTime() + j);
|
||||
if (flag1 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunk.getPos()) && !this.chunkMap.isOutsideOfRange(playerchunk, chunkcoordintpair, true)) { // Spigot // Paper - optimise isOutsideOfRange
|
||||
NaturalSpawner.spawnForChunk(this.level, chunk, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag2);
|
||||
@@ -1030,7 +1046,13 @@ public class ServerChunkCache extends ChunkSource {
|
||||
// this.level.timings.doTickTiles.stopTiming(); // Spigot // Paper
|
||||
}
|
||||
}
|
||||
- });
|
||||
+ } // Paper start - optimise chunk tick iteration
|
||||
+ } finally {
|
||||
+ if (iterator instanceof io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet.Iterator) {
|
||||
+ ((io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet.Iterator<LevelChunk>)iterator).finishedIterating();
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
this.level.timings.chunkTicks.stopTiming(); // Paper
|
||||
this.level.getProfiler().push("customSpawners");
|
||||
if (flag1) {
|
||||
@@ -1039,21 +1061,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
} // Paper - timings
|
||||
}
|
||||
|
||||
- this.level.getProfiler().popPush("broadcast");
|
||||
- this.chunkMap.getChunks().forEach((playerchunk) -> { // Paper - no... just no...
|
||||
- Optional<LevelChunk> optional = ((Either) playerchunk.getTickingChunkFuture().getNow(ChunkHolder.UNLOADED_LEVEL_CHUNK)).left(); // CraftBukkit - decompile error
|
||||
-
|
||||
- Objects.requireNonNull(playerchunk);
|
||||
-
|
||||
- // Paper start - timings
|
||||
- optional.ifPresent(chunk -> {
|
||||
- this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timings
|
||||
- playerchunk.broadcastChanges(chunk);
|
||||
- this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timings
|
||||
- });
|
||||
- // Paper end
|
||||
- });
|
||||
- this.level.getProfiler().pop();
|
||||
+ // Paper - no, iterating just ONCE is expensive enough! Don't do it TWICE! Code moved up
|
||||
this.level.getProfiler().pop();
|
||||
}
|
||||
|
|
@ -5477,7 +5477,7 @@ index ef87c37633cee4ab438f1991144188ade1c4e65f..19d3802becd353e130b785f8286e595e
|
|||
|
||||
protected void purgeStaleTickets() {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index d672c467267ef4d96184e104c35d0379116880db..566c32a71054479257b7fba981507fa2559aa9e6 100644
|
||||
index d672c467267ef4d96184e104c35d0379116880db..be11caf7c0dcdb11e24cfb053cda45ac1867da63 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -48,6 +48,8 @@ import net.minecraft.world.level.storage.LevelData;
|
||||
|
@ -5874,15 +5874,6 @@ index d672c467267ef4d96184e104c35d0379116880db..566c32a71054479257b7fba981507fa2
|
|||
@Nullable
|
||||
@Override
|
||||
public ChunkAccess getChunk(int x, int z, ChunkStatus leastStatus, boolean create) {
|
||||
@@ -444,7 +817,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
gameprofilerfiller.popPush("spawnAndTick");
|
||||
boolean flag2 = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
|
||||
|
||||
- Collections.shuffle(list);
|
||||
+ //Collections.shuffle(list); // Paper - no... just no...
|
||||
Iterator iterator1 = list.iterator();
|
||||
|
||||
while (iterator1.hasNext()) {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
index 9812116e2f28d01423373990ecce0e5ab6229ce2..e66b4837498a8bfefabc4dd95e91ccfba67843e4 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
|
||||
|
|
|
@ -40,13 +40,13 @@ index e954365c9fe7a5f442c4ab31ab8c8db9684409e8..fb9a82b4fabdb73e9a44bcbc20b848d8
|
|||
|
||||
return true;
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 109d6638d8fe035498bd717c180c9143ff00e0ad..9090bc174c0ccb542616e756be66967f55f0a626 100644
|
||||
index 8f5e9f1bdfd2e02512e1341f91b147b16e959e5b..87c9a7ffc69206554cf37c7d2c9939eb3cbea3a9 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -827,6 +827,15 @@ public class ServerChunkCache extends ChunkSource {
|
||||
boolean flag2 = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
|
||||
|
||||
//Collections.shuffle(list); // Paper - no... just no...
|
||||
Collections.shuffle(list);
|
||||
+ // Paper start - call player naturally spawn event
|
||||
+ int chunkRange = level.spigotConfig.mobSpawnRange;
|
||||
+ chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange;
|
||||
|
|
|
@ -272,7 +272,7 @@ index 8868ffcda194e8c2300181a2cdda9337dbde6284..95f195980e28bb59f43e5ca1d5e79ebe
|
|||
|
||||
public String getDebugStatus() {
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 3c36dfa4f4c6025b02ec455d997f13226de75a64..76b56ea346d843aba482c52c4bfe877fdf0e9225 100644
|
||||
index 41d2027cd4cf8f5de7bd59283361f7f1075356cb..24d0b02264e4cced08a60f36b5c41bb350a1dc60 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -881,6 +881,37 @@ public class ServerChunkCache extends ChunkSource {
|
||||
|
@ -316,7 +316,7 @@ index 3c36dfa4f4c6025b02ec455d997f13226de75a64..76b56ea346d843aba482c52c4bfe877f
|
|||
@@ -928,15 +959,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
boolean flag2 = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
|
||||
|
||||
//Collections.shuffle(list); // Paper - no... just no...
|
||||
Collections.shuffle(list);
|
||||
- // Paper start - call player naturally spawn event
|
||||
- int chunkRange = level.spigotConfig.mobSpawnRange;
|
||||
- chunkRange = (chunkRange > level.spigotConfig.viewDistance) ? (byte) level.spigotConfig.viewDistance : chunkRange;
|
||||
|
|
106
patches/server/0827-Optimise-chunk-tick-iteration.patch
Normal file
106
patches/server/0827-Optimise-chunk-tick-iteration.patch
Normal file
|
@ -0,0 +1,106 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Spottedleaf <spottedleaf@spottedleaf.dev>
|
||||
Date: Thu, 7 May 2020 05:48:54 -0700
|
||||
Subject: [PATCH] Optimise chunk tick iteration
|
||||
|
||||
Use a dedicated list of entity ticking chunks to reduce the cost
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
index 51c4ca36221e9af074fa92f6ab94fa7ba5403080..ca16bde30da84e79fef856304ada9e3b8bfb9806 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
||||
@@ -1001,34 +1001,46 @@ public class ServerChunkCache extends ChunkSource {
|
||||
|
||||
this.lastSpawnState = spawnercreature_d;
|
||||
gameprofilerfiller.popPush("filteringLoadedChunks");
|
||||
- List<ServerChunkCache.ChunkAndHolder> list = Lists.newArrayListWithCapacity(l);
|
||||
- Iterator iterator = this.chunkMap.getChunks().iterator();
|
||||
+ // Paper - moved down
|
||||
this.level.timings.chunkTicks.startTiming(); // Paper
|
||||
|
||||
- while (iterator.hasNext()) {
|
||||
- ChunkHolder playerchunk = (ChunkHolder) iterator.next();
|
||||
- LevelChunk chunk = playerchunk.getTickingChunk();
|
||||
-
|
||||
- if (chunk != null) {
|
||||
- list.add(new ServerChunkCache.ChunkAndHolder(chunk, playerchunk));
|
||||
- }
|
||||
- }
|
||||
+ // Paper - moved down
|
||||
|
||||
gameprofilerfiller.popPush("spawnAndTick");
|
||||
boolean flag2 = this.level.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING) && !this.level.players().isEmpty(); // CraftBukkit
|
||||
|
||||
- Collections.shuffle(list);
|
||||
+ // Paper - only shuffle if per-player mob spawning is disabled
|
||||
// Paper - moved natural spawn event up
|
||||
- Iterator iterator1 = list.iterator();
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ Iterator<LevelChunk> iterator1;
|
||||
+ if (this.level.paperConfig.perPlayerMobSpawns) {
|
||||
+ iterator1 = this.entityTickingChunks.iterator();
|
||||
+ } else {
|
||||
+ iterator1 = this.entityTickingChunks.unsafeIterator();
|
||||
+ List<LevelChunk> shuffled = Lists.newArrayListWithCapacity(this.entityTickingChunks.size());
|
||||
+ while (iterator1.hasNext()) {
|
||||
+ shuffled.add(iterator1.next());
|
||||
+ }
|
||||
+ Collections.shuffle(shuffled);
|
||||
+ iterator1 = shuffled.iterator();
|
||||
+ }
|
||||
|
||||
+ try {
|
||||
while (iterator1.hasNext()) {
|
||||
- ServerChunkCache.ChunkAndHolder chunkproviderserver_a = (ServerChunkCache.ChunkAndHolder) iterator1.next();
|
||||
- LevelChunk chunk1 = chunkproviderserver_a.chunk;
|
||||
+ LevelChunk chunk1 = iterator1.next();
|
||||
+ ChunkHolder holder = chunk1.playerChunk;
|
||||
+ if (holder != null) {
|
||||
+ gameprofilerfiller.popPush("broadcast");
|
||||
+ this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing
|
||||
+ holder.broadcastChanges(chunk1);
|
||||
+ this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing
|
||||
+ gameprofilerfiller.pop();
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
ChunkPos chunkcoordintpair = chunk1.getPos();
|
||||
|
||||
- if (this.level.isPositionEntityTicking(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkproviderserver_a.holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning
|
||||
+ if ((true || this.level.isPositionEntityTicking(chunkcoordintpair)) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, false)) { // Paper - optimise anyPlayerCloseEnoughForSpawning & optimise chunk tick iteration
|
||||
chunk1.incrementInhabitedTime(j);
|
||||
- if (flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(chunkproviderserver_a.holder, chunkcoordintpair, true)) { // Spigot // Paper - optimise anyPlayerCloseEnoughForSpawning
|
||||
+ if (flag2 && (this.spawnEnemies || this.spawnFriendlies) && this.level.getWorldBorder().isWithinBounds(chunkcoordintpair) && this.chunkMap.anyPlayerCloseEnoughForSpawning(holder, chunkcoordintpair, true)) { // Spigot // Paper - optimise anyPlayerCloseEnoughForSpawning & optimise chunk tick iteration
|
||||
NaturalSpawner.spawnForChunk(this.level, chunk1, spawnercreature_d, this.spawnFriendlies, this.spawnEnemies, flag1);
|
||||
}
|
||||
|
||||
@@ -1036,7 +1048,16 @@ public class ServerChunkCache extends ChunkSource {
|
||||
this.level.tickChunk(chunk1, k);
|
||||
}
|
||||
}
|
||||
+ // Paper start - optimise chunk tick iteration
|
||||
+ }
|
||||
}
|
||||
+
|
||||
+ } finally {
|
||||
+ if (iterator1 instanceof io.papermc.paper.util.maplist.IteratorSafeOrderedReferenceSet.Iterator safeIterator) {
|
||||
+ safeIterator.finishedIterating();
|
||||
+ }
|
||||
+ }
|
||||
+ // Paper end - optimise chunk tick iteration
|
||||
this.level.timings.chunkTicks.stopTiming(); // Paper
|
||||
gameprofilerfiller.popPush("customSpawners");
|
||||
if (flag2) {
|
||||
@@ -1045,13 +1066,7 @@ public class ServerChunkCache extends ChunkSource {
|
||||
} // Paper - timings
|
||||
}
|
||||
|
||||
- gameprofilerfiller.popPush("broadcast");
|
||||
- list.forEach((chunkproviderserver_a1) -> {
|
||||
- this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing
|
||||
- chunkproviderserver_a1.holder.broadcastChanges(chunkproviderserver_a1.chunk);
|
||||
- this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing
|
||||
- });
|
||||
- gameprofilerfiller.pop();
|
||||
+ // Paper - no, iterating just ONCE is expensive enough! Don't do it TWICE! Code moved up
|
||||
gameprofilerfiller.pop();
|
||||
// Paper start - controlled flush for entity tracker packets
|
||||
List<net.minecraft.network.Connection> disabledFlushes = new java.util.ArrayList<>(this.level.players.size());
|
Loading…
Reference in a new issue