3
0
Mirror von https://github.com/PaperMC/Paper.git synchronisiert 2024-11-16 21:10:17 +01:00

[Bleeding] Implement periodic chunk garbage collector

This adds two settings to bukkit.yml, allowing activation and control of
two chunk garbage collection triggering conditions:
chunk-gc/period-in-ticks controls a periodic GC, run once every N ticks
(default is 600); chunk-gc/load-threshold causes the GC to run once
after every N calls to loadChunk() on a given world (this call is an API
call used by plugins, and is distinct from the path taken for routine
player movement-based loading).  In both cases, setting to zero will
disable the given GC scheduling strategy.

In either case, the act of doing the GC is simply one of scanning the
loaded chunks, seeing which are NOT being used by one or more players
(due to view-distance) and which are not already queued for unload, and
queueing them for a normal unload.  Ultimately, the unload is then
processed the same as if the chunk were unloaded due to leaving the
view-distance range of all players, so the impact on plugins should be
no different (and strategies such as handling the ChunkUnloadEvent in
order to prevent unload will still work).

The initial interval for the periodic GC is randomized on a per-world
basis, in order to avoid all world being GCed at the same time -
minimizing potential lag spikes.
Dieser Commit ist enthalten in:
Mike Primm 2012-12-10 09:38:26 -06:00 committet von Travis Watkins
Ursprung 538de63a03
Commit fb0eed177a
4 geänderte Dateien mit 49 neuen und 0 gelöschten Zeilen

Datei anzeigen

@ -181,6 +181,8 @@ public class WorldServer extends World implements org.bukkit.BlockChangeDelegate
this.P.a(this.getTime()); this.P.a(this.getTime());
this.methodProfiler.b(); this.methodProfiler.b();
this.V(); this.V();
this.getWorld().processChunkGC(); // CraftBukkit
} }
public BiomeMeta a(EnumCreatureType enumcreaturetype, int i, int j, int k) { public BiomeMeta a(EnumCreatureType enumcreaturetype, int i, int j, int k) {

Datei anzeigen

@ -157,6 +157,8 @@ public final class CraftServer implements Server {
private int animalSpawn = -1; private int animalSpawn = -1;
private int waterAnimalSpawn = -1; private int waterAnimalSpawn = -1;
private int ambientSpawn = -1; private int ambientSpawn = -1;
public int chunkGCPeriod = -1;
public int chunkGCLoadThresh = 0;
private File container; private File container;
private WarningState warningState = WarningState.DEFAULT; private WarningState warningState = WarningState.DEFAULT;
private final BooleanWrapper online = new BooleanWrapper(); private final BooleanWrapper online = new BooleanWrapper();
@ -202,6 +204,8 @@ public final class CraftServer implements Server {
ambientSpawn = configuration.getInt("spawn-limits.ambient"); ambientSpawn = configuration.getInt("spawn-limits.ambient");
console.autosavePeriod = configuration.getInt("ticks-per.autosave"); console.autosavePeriod = configuration.getInt("ticks-per.autosave");
warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); warningState = WarningState.value(configuration.getString("settings.deprecated-verbose"));
chunkGCPeriod = configuration.getInt("chunk-gc.period-in-ticks");
chunkGCLoadThresh = configuration.getInt("chunk-gc.load-threshold");
updater = new AutoUpdater(new BukkitDLUpdaterService(configuration.getString("auto-updater.host")), getLogger(), configuration.getString("auto-updater.preferred-channel")); updater = new AutoUpdater(new BukkitDLUpdaterService(configuration.getString("auto-updater.host")), getLogger(), configuration.getString("auto-updater.preferred-channel"));
updater.setEnabled(configuration.getBoolean("auto-updater.enabled")); updater.setEnabled(configuration.getBoolean("auto-updater.enabled"));
@ -537,6 +541,8 @@ public final class CraftServer implements Server {
ambientSpawn = configuration.getInt("spawn-limits.ambient"); ambientSpawn = configuration.getInt("spawn-limits.ambient");
warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); warningState = WarningState.value(configuration.getString("settings.deprecated-verbose"));
console.autosavePeriod = configuration.getInt("ticks-per.autosave"); console.autosavePeriod = configuration.getInt("ticks-per.autosave");
chunkGCPeriod = configuration.getInt("chunk-gc.period-in-ticks");
chunkGCLoadThresh = configuration.getInt("chunk-gc.load-threshold");
for (WorldServer world : console.worlds) { for (WorldServer world : console.worlds) {
world.difficulty = difficulty; world.difficulty = difficulty;

Datei anzeigen

@ -1,6 +1,7 @@
package org.bukkit.craftbukkit; package org.bukkit.craftbukkit;
import java.io.File; import java.io.File;
import java.util.Iterator;
import java.util.Set; import java.util.Set;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -58,6 +59,8 @@ public class CraftWorld implements World {
private int animalSpawn = -1; private int animalSpawn = -1;
private int waterAnimalSpawn = -1; private int waterAnimalSpawn = -1;
private int ambientSpawn = -1; private int ambientSpawn = -1;
private int chunkLoadCount = 0;
private int chunkGCTickCount;
private static final Random rand = new Random(); private static final Random rand = new Random();
@ -66,6 +69,10 @@ public class CraftWorld implements World {
this.generator = gen; this.generator = gen;
environment = env; environment = env;
if (server.chunkGCPeriod > 0) {
chunkGCTickCount = rand.nextInt(server.chunkGCPeriod);
}
} }
public Block getBlockAt(int x, int y, int z) { public Block getBlockAt(int x, int y, int z) {
@ -226,6 +233,7 @@ public class CraftWorld implements World {
} }
public boolean loadChunk(int x, int z, boolean generate) { public boolean loadChunk(int x, int z, boolean generate) {
chunkLoadCount++;
if (generate) { if (generate) {
// Use the default variant of loadChunk when generate == true. // Use the default variant of loadChunk when generate == true.
return world.chunkProviderServer.getChunkAt(x, z) != null; return world.chunkProviderServer.getChunkAt(x, z) != null;
@ -1233,4 +1241,34 @@ public class CraftWorld implements World {
public boolean isGameRule(String rule) { public boolean isGameRule(String rule) {
return getHandle().getGameRules().e(rule); return getHandle().getGameRules().e(rule);
} }
public void processChunkGC() {
chunkGCTickCount++;
if (chunkLoadCount >= server.chunkGCLoadThresh && server.chunkGCLoadThresh > 0) {
chunkLoadCount = 0;
} else if (chunkGCTickCount >= server.chunkGCPeriod && server.chunkGCPeriod > 0) {
chunkGCTickCount = 0;
} else {
return;
}
ChunkProviderServer cps = world.chunkProviderServer;
Iterator<net.minecraft.server.Chunk> iter = cps.chunks.values().iterator();
while (iter.hasNext()) {
net.minecraft.server.Chunk chunk = iter.next();
// If in use, skip it
if (isChunkInUse(chunk.x, chunk.z)) {
continue;
}
// Already unloading?
if (cps.unloadQueue.contains(chunk.x, chunk.z)) {
continue;
}
// Add unload request
cps.queueUnload(chunk.x, chunk.z);
}
}
} }

Datei anzeigen

@ -30,6 +30,9 @@ spawn-limits:
animals: 15 animals: 15
water-animals: 5 water-animals: 5
ambient: 15 ambient: 15
chunk-gc:
period-in-ticks: 600
load-threshold: 0
ticks-per: ticks-per:
animal-spawns: 400 animal-spawns: 400
monster-spawns: 1 monster-spawns: 1