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.
This commit is contained in:
Aikar 2020-05-25 12:34:03 -04:00
parent 07ab0369ac
commit 6480eba1cc

View File

@ -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<Ticket<?>> 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<Ticket<?>> 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<Either<IChunkAccess, PlayerChunk.Failure>> 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<Ticket<?>> 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) {