From 6480eba1ccc08772d16e3a2adaa583730d7136c1 Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 25 May 2020 12:34:03 -0400 Subject: [PATCH] Fix unloading inaccessible chunks too fast regressing gen speed A chunk was loaded but not yet finished in use and was unloaded too early. This caused it to be reloaded again or caused crashes. Now also check if the chunk pops out of the unload queue that it also doesn't now have a ticket either. --- .../Unload-leaked-Cached-Chunks.patch | 53 ++++++++++++------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/Spigot-Server-Patches/Unload-leaked-Cached-Chunks.patch b/Spigot-Server-Patches/Unload-leaked-Cached-Chunks.patch index 36bba6cac..09f26878f 100644 --- a/Spigot-Server-Patches/Unload-leaked-Cached-Chunks.patch +++ b/Spigot-Server-Patches/Unload-leaked-Cached-Chunks.patch @@ -28,7 +28,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start - remove inaccessible chunks leaked + else if (playerchunk.getTicketLevel() == playerchunk.oldTicketLevel && + playerChunkMap.unloadQueue.size() < 100 && -+ (playerchunk.lastStatusChange == 0 || world.getTime() - playerchunk.lastStatusChange > 20) && ++ (playerchunk.lastActivity == 0 || world.getTime() - playerchunk.lastActivity > 20*15) && + PlayerChunk.getChunkState(playerchunk.getTicketLevel()) == PlayerChunk.State.INACCESSIBLE + ) { + ChunkStatus chunkHolderStatus = playerchunk.getChunkHolderStatus(); @@ -36,23 +36,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (chunkHolderStatus != null && !chunkHolderStatus.isAtLeastStatus(desiredStatus)) { + return; + } -+ -+ if (playerchunk.lastStatusChange == 0) { -+ playerchunk.lastStatusChange = world.getTime(); -+ } else { -+ Chunk chunk = playerchunk.getChunk(); -+ if (chunk != null && chunk.isAnyNeighborsLoaded()) { -+ playerchunk.lastStatusChange = world.getTime()+(20*5); -+ return; -+ } -+ long key = playerchunk.location.pair(); -+ ArraySetSorted> tickets = playerChunkMap.chunkDistanceManager.tickets.get(key); -+ if (tickets == null || tickets.isEmpty()) { -+ playerchunk.lastStatusChange = world.getTime()+(20*30); -+ playerChunkMap.unloadQueue.add(key); -+ } else { -+ playerchunk.lastStatusChange = world.getTime()+(20*5); -+ } ++ playerchunk.lastActivity = world.getTime(); ++ Chunk chunk = playerchunk.getChunk(); ++ if ((chunk != null && chunk.isAnyNeighborsLoaded()) || !playerchunk.neighborPriorities.isEmpty()) { ++ return; ++ } ++ long key = playerchunk.location.pair(); ++ ArraySetSorted> tickets = playerChunkMap.chunkDistanceManager.tickets.get(key); ++ if (tickets == null || tickets.isEmpty()) { ++ playerChunkMap.unloadQueue.add(key); + } + // Paper end + } @@ -67,7 +59,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 long lastAutoSaveTime; // Paper - incremental autosave long inactiveTimeStart; // Paper - incremental autosave -+ long lastStatusChange; // Paper - fix chunk leak ++ long lastActivity; // Paper - fix chunk leak // Paper start - optimise isOutsideOfRange // cached here to avoid a map lookup @@ -75,7 +67,28 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 protected void a(PlayerChunkMap playerchunkmap) { ChunkStatus chunkstatus = getChunkStatus(this.oldTicketLevel); ChunkStatus chunkstatus1 = getChunkStatus(this.ticketLevel); -+ if (oldTicketLevel != ticketLevel) lastStatusChange = chunkMap.world.getTime(); // Paper - chunk leak ++ if (oldTicketLevel != ticketLevel) lastActivity = chunkMap.world.getTime(); // Paper - chunk leak boolean flag = this.oldTicketLevel <= PlayerChunkMap.GOLDEN_TICKET; boolean flag1 = this.ticketLevel <= PlayerChunkMap.GOLDEN_TICKET; // Paper - diff on change: (flag1 = new ticket level is in loadable range) PlayerChunk.State playerchunk_state = getChunkState(this.oldTicketLevel); +diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java ++++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java +@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + } + })); + } ++ playerchunk.lastActivity = world.getTime(); // Paper - chunk leak + + ChunkStatus chunkstatus = (ChunkStatus) intfunction.apply(j1); + CompletableFuture> completablefuture = playerchunk.a(chunkstatus, this); +@@ -0,0 +0,0 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { + while (longiterator.hasNext()) { // Spigot + long j = longiterator.nextLong(); + longiterator.remove(); // Spigot ++ ArraySetSorted> tickets = chunkDistanceManager.tickets.get(j); // Paper - chunk leak ++ if (tickets != null && !tickets.isEmpty()) continue; // Paper - ticket got added, don't remove + PlayerChunk playerchunk = (PlayerChunk) this.updatingChunks.remove(j); + + if (playerchunk != null) {