From c5851b2a5288702fd63f5ab5d199868ab6222d48 Mon Sep 17 00:00:00 2001 From: Shane Freeder Date: Sun, 9 Jun 2019 03:53:22 +0100 Subject: [PATCH] incremental chunk saving diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java index b854061983..58109e1308 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -494,4 +494,19 @@ public class PaperWorldConfig { keepLoadedRange = (short) (getInt("keep-spawn-loaded-range", Math.min(spigotConfig.viewDistance, 10)) * 16); log( "Keep Spawn Loaded Range: " + (keepLoadedRange/16)); } + + public int autoSavePeriod = -1; + private void autoSavePeriod() { + autoSavePeriod = getInt("auto-save-interval", -1); + if (autoSavePeriod > 0) { + log("Auto Save Interval: " +autoSavePeriod + " (" + (autoSavePeriod / 20) + "s)"); + } else if (autoSavePeriod < 0) { + autoSavePeriod = net.minecraft.server.MinecraftServer.getServer().autosavePeriod; + } + } + + public int maxAutoSaveChunksPerTick = 24; + private void maxAutoSaveChunksPerTick() { + maxAutoSaveChunksPerTick = getInt("max-auto-save-chunks-per-tick", 24); + } } diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java index ef07f665b7..d89ad4e390 100644 --- a/src/main/java/net/minecraft/server/Chunk.java +++ b/src/main/java/net/minecraft/server/Chunk.java @@ -42,7 +42,7 @@ public class Chunk implements IChunkAccess { private TickList o; private TickList p; private boolean q; - private long lastSaved; + public long lastSaved; // Paper private volatile boolean s; private long t; @Nullable diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java index 184f1b00f0..13e862aa9f 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -156,6 +156,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant processQueue = new java.util.concurrent.ConcurrentLinkedQueue(); public int autosavePeriod; + public boolean serverAutoSave = false; // Paper public File bukkitDataPackFolder; public CommandDispatcher vanillaCommandDispatcher; private boolean forceTicks; @@ -1072,14 +1073,22 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit + //if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit // Paper - move down MinecraftServer.LOGGER.debug("Autosave started"); + serverAutoSave = (autosavePeriod > 0 && this.ticks % autosavePeriod == 0); // Paper this.methodProfiler.enter("save"); + if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // Paper this.playerList.savePlayers(); - this.saveChunks(true, false, false); + }// Paper + // Paper start + for (World world : getWorlds()) { + if (world.paperConfig.autoSavePeriod > 0) world.getWorld().save(false); + } + // Paper end + this.methodProfiler.exit(); MinecraftServer.LOGGER.debug("Autosave finished"); - } + //} // Paper this.methodProfiler.enter("snooper"); if (((DedicatedServer) this).getDedicatedServerProperties().snooperEnabled && !this.snooper.d() && this.ticks > 100) { // Spigot diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java index c091007d8c..67aa9325b6 100644 --- a/src/main/java/net/minecraft/server/PlayerChunkMap.java +++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java @@ -295,15 +295,29 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d { }); PlayerChunkMap.LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", this.x.getName()); } else { - this.visibleChunks.values().stream().filter(PlayerChunk::hasBeenLoaded).forEach((playerchunk) -> { + // Paper start + int savedThisTick = 0; + for (PlayerChunk playerchunk : this.visibleChunks.values()) { + if (!playerchunk.hasBeenLoaded()) continue; + // Paper end IChunkAccess ichunkaccess = (IChunkAccess) playerchunk.getChunkSave().getNow(null); // CraftBukkit - decompile error if (ichunkaccess instanceof ProtoChunkExtension || ichunkaccess instanceof Chunk) { - this.saveChunk(ichunkaccess); + // paper start + boolean shouldSave = true; + + if (ichunkaccess instanceof Chunk) { + shouldSave = ((Chunk) ichunkaccess).lastSaved + world.paperConfig.autoSavePeriod <= world.getTime(); + } + + if (shouldSave && this.saveChunk(ichunkaccess)) ++savedThisTick; playerchunk.l(); + if (savedThisTick >= world.paperConfig.maxAutoSaveChunksPerTick) { + return; + } } - - }); + }; + // paper end } } diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java index 92aad060ef..c650f40b0d 100644 --- a/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java @@ -757,6 +757,7 @@ public class WorldServer extends World { if (!flag1) { org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { // Paper + if (flag || server.serverAutoSave) { // Paper if (iprogressupdate != null) { iprogressupdate.a(new ChatMessage("menu.savingLevel", new Object[0])); } @@ -765,6 +766,7 @@ public class WorldServer extends World { if (iprogressupdate != null) { iprogressupdate.c(new ChatMessage("menu.savingChunks", new Object[0])); } + } // Paper timings.worldSaveChunks.startTiming(); // Paper chunkproviderserver.save(flag); diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index 0c53795306..4e60931cd8 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -1151,13 +1151,19 @@ public class CraftWorld implements World { // Paper end @Override + // Paper start public void save() { + save(true); + } + + public void save(boolean forceSave) { + // Paper end this.server.checkSaveState(); try { boolean oldSave = world.savingDisabled; world.savingDisabled = false; - world.save(null, false, false); + world.save(null, forceSave, false); // Paper world.savingDisabled = oldSave; } catch (ExceptionWorldConflict ex) { -- 2.21.0