2016-10-21 21:08:34 +00:00
From 11a88b05460b3817a48f74e5326416ef447b9eb2 Mon Sep 17 00:00:00 2001
2016-09-22 02:12:56 +00:00
From: Aikar <aikar@aikar.co>
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
2016-10-21 20:42:49 +00:00
index 3828da7..7e53fee 100644
2016-09-22 02:12:56 +00:00
--- 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
2016-10-21 20:42:49 +00:00
index a4f7e4d..fb06496 100644
2016-09-22 02:12:56 +00:00
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
2016-09-26 05:50:26 +00:00
@@ -114,6 +114,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
public final Thread primaryThread;
public java.util.Queue<Runnable> processQueue = new java.util.concurrent.ConcurrentLinkedQueue<Runnable>();
public int autosavePeriod;
+ public boolean serverAutoSave = false; // Paper
// CraftBukkit end
public MinecraftServer(OptionSet options, Proxy proxy, DataConverterManager dataconvertermanager, YggdrasilAuthenticationService yggdrasilauthenticationservice, MinecraftSessionService minecraftsessionservice, GameProfileRepository gameprofilerepository, UserCache usercache) {
2016-10-21 20:42:49 +00:00
@@ -745,22 +746,26 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs
2016-09-22 02:12:56 +00:00
this.q.b().a(agameprofile);
}
- if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit
this.methodProfiler.a("save");
+
2016-09-26 05:50:26 +00:00
+ serverAutoSave = (autosavePeriod > 0 && this.ticks % autosavePeriod == 0); // Paper
+ if (serverAutoSave) { // CraftBukkit // Paper
2016-09-22 02:12:56 +00:00
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();
- }
+ //} // 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
2016-10-21 20:42:49 +00:00
index fc33575..81712ff 100644
2016-09-22 02:12:56 +00:00
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
2016-10-21 20:42:49 +00:00
@@ -1017,8 +1017,9 @@ public class WorldServer extends World implements IAsyncTaskHandler {
2016-09-22 02:12:56 +00:00
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
2016-10-21 20:42:49 +00:00
timings.worldSave.startTiming(); // Paper
+ if (flag || server.serverAutoSave) { // Paper
2016-09-22 02:12:56 +00:00
if (iprogressupdate != null) {
iprogressupdate.a("Saving level");
}
2016-10-21 20:42:49 +00:00
@@ -1027,6 +1028,7 @@ public class WorldServer extends World implements IAsyncTaskHandler {
2016-09-26 05:50:26 +00:00
if (iprogressupdate != null) {
iprogressupdate.c("Saving chunks");
}
2016-10-21 20:42:49 +00:00
+ } // Paper
timings.worldSaveChunks.startTiming(); // Paper
chunkproviderserver.a(flag);
2016-09-22 02:12:56 +00:00
--
2016-10-21 20:28:44 +00:00
2.9.3
2016-09-22 02:12:56 +00:00