Optimize Spare Chunk loads to be removed faster

this has technically been a longer standing problem, but if an async
chunk loads after a chunk has been removed from the chunk map, it would
be treated as any other spare chunk and kept loaded until Chunk GC kicks in.

This fixes that, but also obsoletes ChunkGC in that anytime we load a spare
chunk (a chunk outside of any players view distance), we will immediately
mark it for unload.

This should reduce the amount of spare chunks loaded on a server.
This commit is contained in:
Aikar 2018-09-30 20:34:05 -04:00
parent 424d794178
commit 065868036c
5 changed files with 58 additions and 11 deletions

View File

@ -1418,7 +1418,7 @@ index 22a262bb60..40ec398eef 100644
if (flag) { if (flag) {
packetdataserializer.writeBytes(chunksection.getSkyLightArray().asBytes()); packetdataserializer.writeBytes(chunksection.getSkyLightArray().asBytes());
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index f8d8a44a88..e7d465fb8a 100644 index 84896d6f6b..2a889dc20a 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java --- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java +++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -0,0 +0,0 @@ public class PlayerChunk { @@ -0,0 +0,0 @@ public class PlayerChunk {

View File

@ -1215,7 +1215,7 @@ index 0000000000..47d9ecdbf1
+ +
+} +}
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index e7d465fb8a..61de438fdf 100644 index 2a889dc20a..242691d89d 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java --- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java +++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -0,0 +0,0 @@ public class PlayerChunk { @@ -0,0 +0,0 @@ public class PlayerChunk {
@ -1265,8 +1265,8 @@ index e7d465fb8a..61de438fdf 100644
+ } + }
+ // Paper end + // Paper end
// Paper start - delay chunk unloads // Paper start - delay chunk unloads
public final void markChunkUsed() { private void markChunkUsed() {
if (chunk != null && chunk.scheduledForUnload != null) { if (chunk == null) {
@@ -0,0 +0,0 @@ public class PlayerChunk { @@ -0,0 +0,0 @@ public class PlayerChunk {
ChunkProviderServer chunkproviderserver = playerchunkmap.getWorld().getChunkProviderServer(); ChunkProviderServer chunkproviderserver = playerchunkmap.getWorld().getChunkProviderServer();
@ -1279,8 +1279,8 @@ index e7d465fb8a..61de438fdf 100644
} }
@@ -0,0 +0,0 @@ public class PlayerChunk { @@ -0,0 +0,0 @@ public class PlayerChunk {
if (this.c.isEmpty()) { chunkHasPlayers = false; // Paper - delay chunk unloads
this.i = this.playerChunkMap.getWorld().getTime(); markChunkUsed(); // Paper - delay chunk unloads
} }
+ checkHighPriority(entityplayer); // Paper + checkHighPriority(entityplayer); // Paper

View File

@ -33,7 +33,7 @@ index af69342e6c..ca7efc9175 100644
+ } + }
} }
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index 3f4a8f21c0..f8d8a44a88 100644 index abf5a7554d..84896d6f6b 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java --- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java +++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -0,0 +0,0 @@ public class PlayerChunk { @@ -0,0 +0,0 @@ public class PlayerChunk {

View File

@ -16,6 +16,9 @@ before it actually unloads, which is maintained separately from ChunkGC.
This allows servers with smaller worlds who do less long distance exploring to stop This allows servers with smaller worlds who do less long distance exploring to stop
wasting cpu cycles on saving/unloading/reloading chunks repeatedly. wasting cpu cycles on saving/unloading/reloading chunks repeatedly.
This also makes the Chunk GC System useless, by auto scheduling unload as soon as
a spare chunk is added to the server thats outside of view distance.
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index ff1a2046f6..0cd15c17e8 100644 index ff1a2046f6..0cd15c17e8 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@ -51,6 +54,26 @@ index 41d3aaa80b..824727ec66 100644
public final int locX; public final int locX;
public final int locZ; public final int locZ;
private boolean l; public boolean needsGapCheck() { return l; } // Paper - OBFHELPER private boolean l; public boolean needsGapCheck() { return l; } // Paper - OBFHELPER
diff --git a/src/main/java/net/minecraft/server/ChunkMap.java b/src/main/java/net/minecraft/server/ChunkMap.java
index df967ff07d..a3dc90fd2b 100644
--- a/src/main/java/net/minecraft/server/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/ChunkMap.java
@@ -0,0 +0,0 @@ public class ChunkMap extends Long2ObjectOpenHashMap<Chunk> {
}
}
}
+ // Paper start - if this is a spare chunk (not part of any players view distance), go ahead and queue it for unload.
+ if (!((WorldServer)chunk.world).getPlayerChunkMap().isChunkInUse(chunk.locX, chunk.locZ)) {
+ if (chunk.world.paperConfig.delayChunkUnloadsBy > 0) {
+ chunk.scheduledForUnload = System.currentTimeMillis();
+ } else {
+ ((WorldServer) chunk.world).getChunkProviderServer().unload(chunk);
+ }
+ }
+ // Paper end
chunk.world.timings.syncChunkLoadPostTimer.stopTiming(); // Paper
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 2d10f4aa37..719d5deb2c 100644 index 2d10f4aa37..719d5deb2c 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java --- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
@ -76,7 +99,7 @@ index 2d10f4aa37..719d5deb2c 100644
this.chunkScheduler.a(booleansupplier); this.chunkScheduler.a(booleansupplier);
} }
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index ac0e90eeca..3f4a8f21c0 100644 index ac0e90eeca..abf5a7554d 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java --- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java +++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -0,0 +0,0 @@ public class PlayerChunk { @@ -0,0 +0,0 @@ public class PlayerChunk {
@ -87,11 +110,17 @@ index ac0e90eeca..3f4a8f21c0 100644
} }
}; };
+ // Paper start - delay chunk unloads + // Paper start - delay chunk unloads
+ public final void markChunkUsed() { + private void markChunkUsed() {
+ if (chunk != null && chunk.scheduledForUnload != null) { + if (chunk == null) {
+ return;
+ }
+ if (!chunkHasPlayers) {
+ chunk.scheduledForUnload = null; + chunk.scheduledForUnload = null;
+ } else if (chunk.scheduledForUnload == null) {
+ chunk.scheduledForUnload = System.currentTimeMillis();
+ } + }
+ } + }
+ private boolean chunkHasPlayers = true;
+ // Paper end + // Paper end
// CraftBukkit end // CraftBukkit end
@ -104,6 +133,24 @@ index ac0e90eeca..3f4a8f21c0 100644
} }
public ChunkCoordIntPair a() { public ChunkCoordIntPair a() {
@@ -0,0 +0,0 @@ public class PlayerChunk {
} else {
if (this.c.isEmpty()) {
this.i = this.playerChunkMap.getWorld().getTime();
+ chunkHasPlayers = false; // Paper - delay chunk unloads
+ markChunkUsed(); // Paper - delay chunk unloads
}
this.c.add(entityplayer);
@@ -0,0 +0,0 @@ public class PlayerChunk {
this.c.remove(entityplayer);
if (this.c.isEmpty()) {
+ chunkHasPlayers = true; // Paper - delay chunk unloads
+ markChunkUsed(); // Paper - delay chunk unloads
this.playerChunkMap.b(this);
}
@@ -0,0 +0,0 @@ public class PlayerChunk { @@ -0,0 +0,0 @@ public class PlayerChunk {
return true; return true;
} else { } else {

View File

@ -41,7 +41,7 @@ index 895eb60854..350479dc68 100644
} }
diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java
index 61de438fdf..fca88c3018 100644 index 242691d89d..86f0fb3c2a 100644
--- a/src/main/java/net/minecraft/server/PlayerChunk.java --- a/src/main/java/net/minecraft/server/PlayerChunk.java
+++ b/src/main/java/net/minecraft/server/PlayerChunk.java +++ b/src/main/java/net/minecraft/server/PlayerChunk.java
@@ -0,0 +0,0 @@ public class PlayerChunk { @@ -0,0 +0,0 @@ public class PlayerChunk {