From 0fc642a1896c42047c3ae06a98fb2552d3dce95c Mon Sep 17 00:00:00 2001 From: Aikar Date: Wed, 21 Sep 2016 22:12:56 -0400 Subject: [PATCH] Auto Save Improvements Makes Auto Save Rate setting configurable per-world. If the auto save rate is left -1, the global bukkit.yml value will be used. Process auto save every tick instead of once per auto tick interval, so that chunk saves will distribute over many ticks instead of all at once. Re-introduce a cap per tick for auto save (Spigot disabled the vanilla cap) and make it configurable. --- .../0172-Auto-Save-Improvements.patch | 127 ++++++++++++++++++ .../0172-Incremental-Auto-Saving.patch | 66 --------- 2 files changed, 127 insertions(+), 66 deletions(-) create mode 100644 Spigot-Server-Patches/0172-Auto-Save-Improvements.patch delete mode 100644 Spigot-Server-Patches/0172-Incremental-Auto-Saving.patch diff --git a/Spigot-Server-Patches/0172-Auto-Save-Improvements.patch b/Spigot-Server-Patches/0172-Auto-Save-Improvements.patch new file mode 100644 index 0000000000..c05f7d33f3 --- /dev/null +++ b/Spigot-Server-Patches/0172-Auto-Save-Improvements.patch @@ -0,0 +1,127 @@ +From 174325d842704ca0cdfdd21586234f2426246090 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 19 Sep 2016 23:16:39 -0400 +Subject: [PATCH] Auto Save Improvements + +Makes Auto Save Rate setting configurable per-world. If the auto save rate is left -1, the global bukkit.yml value will be used. + +Process auto save every tick instead of once per auto tick interval, so that chunk saves will distribute over many ticks instead of all at once. + +Re-introduce a cap per tick for auto save (Spigot disabled the vanilla cap) and make it configurable. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index fb67306..eacb1f6 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -2,6 +2,7 @@ package com.destroystokyo.paper; + + import java.util.List; + ++import net.minecraft.server.MinecraftServer; + import org.bukkit.Bukkit; + import org.bukkit.configuration.file.YamlConfiguration; + import org.spigotmc.SpigotWorldConfig; +@@ -377,4 +378,19 @@ public class PaperWorldConfig { + private void elytraHitWallDamage() { + elytraHitWallDamage = getBoolean("elytra-hit-wall-damage", true); + } ++ ++ 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 = 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 683a6dd..547628a 100644 +--- a/src/main/java/net/minecraft/server/Chunk.java ++++ b/src/main/java/net/minecraft/server/Chunk.java +@@ -960,7 +960,7 @@ public class Chunk { + if (this.t && this.world.getTime() != this.lastSaved || this.s) { + return true; + } +- } else if (this.t && this.world.getTime() >= this.lastSaved + MinecraftServer.getServer().autosavePeriod * 4) { // Spigot - Only save if we've passed 2 auto save intervals without modification ++ } else if (this.t && this.world.getTime() >= this.lastSaved + world.paperConfig.autoSavePeriod) { // Spigot // Paper - Make world configurable and incremental + return true; + } + +diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java +index 1ba02f1..65de280 100644 +--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java +@@ -1,5 +1,6 @@ + package net.minecraft.server; + ++import com.destroystokyo.paper.PaperConfig; + import com.google.common.collect.Lists; + import com.google.common.collect.Sets; + import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +@@ -265,7 +266,7 @@ public class ChunkProviderServer implements IChunkProvider { + this.saveChunk(chunk); + chunk.f(false); + ++i; +- if (i == 24 && !flag && false) { // Spigot ++ if (!flag && i >= world.paperConfig.maxAutoSaveChunksPerTick) { // Spigot - // Paper - Incremental Auto Save - cap max per tick + return false; + } + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 8ca8fbf..2f9ce91 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -745,24 +745,27 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs + this.q.b().a(agameprofile); + } + +- if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit + MinecraftTimings.worldSaveTimer.startTiming(); // Spigot + this.methodProfiler.a("save"); ++ ++ if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit + this.v.savePlayers(); + // Spigot Start ++ } // Paper - Incremental Auto Saving ++ + // We replace this with saving each individual world as this.saveChunks(...) is broken, + // and causes the main thread to sleep for random amounts of time depending on chunk activity + // Also pass flag to only save modified chunks + server.playerCommandState = true; + for (World world : worlds) { +- world.getWorld().save(false); ++ if (world.paperConfig.autoSavePeriod > 0) world.getWorld().save(false); // Paper - Incremental / Configurable Auto Saving + } + server.playerCommandState = false; + // this.saveChunks(true); + // Spigot End + this.methodProfiler.b(); + MinecraftTimings.worldSaveTimer.stopTiming(); // Spigot +- } ++ //} // Paper - Incremental Auto Saving + + this.methodProfiler.a("tallying"); + this.h[this.ticks % 100] = System.nanoTime() - i; +diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java +index 5ed6d3e..a47bfee 100644 +--- a/src/main/java/net/minecraft/server/WorldServer.java ++++ b/src/main/java/net/minecraft/server/WorldServer.java +@@ -1024,7 +1024,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { + ChunkProviderServer chunkproviderserver = this.getChunkProviderServer(); + + if (chunkproviderserver.e()) { +- org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit ++ if (flag) org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit // Paper - Incremental Auto Saving - Only fire event on full save + if (iprogressupdate != null) { + iprogressupdate.a("Saving level"); + } +-- +2.9.3 + diff --git a/Spigot-Server-Patches/0172-Incremental-Auto-Saving.patch b/Spigot-Server-Patches/0172-Incremental-Auto-Saving.patch deleted file mode 100644 index 86123f96e2..0000000000 --- a/Spigot-Server-Patches/0172-Incremental-Auto-Saving.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 264f8e1152df767154c82b0723c0b4f4421e2157 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 19 Sep 2016 23:16:39 -0400 -Subject: [PATCH] Incremental Auto Saving - -Process auto save every tick instead of once per auto tick interval, so that chunk saves will distribute over many ticks instead of all at once. - -diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java -index 683a6dd..4a51eff 100644 ---- a/src/main/java/net/minecraft/server/Chunk.java -+++ b/src/main/java/net/minecraft/server/Chunk.java -@@ -960,7 +960,7 @@ public class Chunk { - if (this.t && this.world.getTime() != this.lastSaved || this.s) { - return true; - } -- } else if (this.t && this.world.getTime() >= this.lastSaved + MinecraftServer.getServer().autosavePeriod * 4) { // Spigot - Only save if we've passed 2 auto save intervals without modification -+ } else if (this.t && this.world.getTime() >= this.lastSaved + MinecraftServer.getServer().autosavePeriod) { // Spigot // Paper - Remove broken change - return true; - } - -diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index 1ba02f1..0410bf2 100644 ---- a/src/main/java/net/minecraft/server/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java -@@ -265,7 +265,7 @@ public class ChunkProviderServer implements IChunkProvider { - this.saveChunk(chunk); - chunk.f(false); - ++i; -- if (i == 24 && !flag && false) { // Spigot -+ if (i == 24 && !flag) { // Spigot - // Paper - Incremental Auto Save - cap to 24 per tick - return false; - } - } -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 8ca8fbf..8deb679 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -745,10 +745,10 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs - this.q.b().a(agameprofile); - } - -- if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit -+ if (autosavePeriod > 0 /*&& this.ticks % autosavePeriod == 0*/) { // CraftBukkit // Paper - Incremental Auto Saving - MinecraftTimings.worldSaveTimer.startTiming(); // Spigot - this.methodProfiler.a("save"); -- this.v.savePlayers(); -+ if (this.ticks % autosavePeriod == 0) this.v.savePlayers(); // Paper - Incremental Auto Saving - // Spigot Start - // We replace this with saving each individual world as this.saveChunks(...) is broken, - // and causes the main thread to sleep for random amounts of time depending on chunk activity -diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index 5ed6d3e..a47bfee 100644 ---- a/src/main/java/net/minecraft/server/WorldServer.java -+++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -1024,7 +1024,7 @@ public class WorldServer extends World implements IAsyncTaskHandler { - ChunkProviderServer chunkproviderserver = this.getChunkProviderServer(); - - if (chunkproviderserver.e()) { -- org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit -+ if (flag) org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); // CraftBukkit // Paper - Incremental Auto Saving - Only fire event on full save - if (iprogressupdate != null) { - iprogressupdate.a("Saving level"); - } --- -2.9.3 -