Compare commits

..

3 Commits

Author SHA1 Message Date
MrHua269
650ce2770d Added flush threshold for linear region file 2024-04-20 13:34:16 +00:00
MrHua269
ce500bf638 Added flush threshold for linear region file 2024-04-20 13:33:34 +00:00
MrHua269
48f34a6146 Refactor linear flushing again 2024-04-20 13:15:22 +00:00

View File

@@ -93,10 +93,10 @@ index 0000000000000000000000000000000000000000..dcfbabf54b19a4c29d5c95830242c5c2
+}
diff --git a/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFile.java b/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..dc5a5f42c9ca7a50295c18424722568a3ad33fa5
index 0000000000000000000000000000000000000000..7e551a5fb7db6a0aa4f60b15587be2b716c54000
--- /dev/null
+++ b/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFile.java
@@ -0,0 +1,324 @@
@@ -0,0 +1,341 @@
+package dev.kaiijumc.kaiiju.region;
+
+import com.github.luben.zstd.ZstdInputStream;
@@ -120,6 +120,7 @@ index 0000000000000000000000000000000000000000..dc5a5f42c9ca7a50295c18424722568a
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class LinearRegionFile implements AbstractRegionFile, AutoCloseable {
@@ -129,7 +130,7 @@ index 0000000000000000000000000000000000000000..dc5a5f42c9ca7a50295c18424722568a
+ private static final int FOOTER_SIZE = 8;
+ private static final Logger LOGGER = LogUtils.getLogger();
+ private static final List<Byte> SUPPORTED_VERSIONS = Arrays.asList((byte) 1, (byte) 2);
+ private static final LinearRegionFileFlusher linearRegionFileFlusher = new LinearRegionFileFlusher();
+ public static final LinearRegionFileFlusher linearRegionFileFlusher = new LinearRegionFileFlusher();
+
+ private final byte[][] buffer = new byte[1024][];
+ private final int[] bufferUncompressedSize = new int[1024];
@@ -147,6 +148,9 @@ index 0000000000000000000000000000000000000000..dc5a5f42c9ca7a50295c18424722568a
+ public boolean closed = false;
+ public Path path;
+
+ public volatile boolean savingScheduled = true;
+ public final AtomicInteger dirtyChunkCount = new AtomicInteger(0);
+
+
+ public LinearRegionFile(Path file, int compression) throws IOException {
+ this.path = file;
@@ -225,14 +229,20 @@ index 0000000000000000000000000000000000000000..dc5a5f42c9ca7a50295c18424722568a
+ }
+
+ public void flush() throws IOException {
+ if (getAndResetSaveMarker()) flushWrapper(); // sync
+ if (getAndResetSaveMarker()) {
+ this.savingScheduled = false; //cancel async saving
+ flushWrapper(); // sync
+ }
+ }
+
+ private void markToSave() {
+ linearRegionFileFlusher.scheduleSave(this);
+ markedToSave.set(true);
+ }
+
+ private void signalToSave(){
+ linearRegionFileFlusher.scheduleSave(this);
+ }
+
+ public boolean getAndResetSaveMarker() {
+ return markedToSave.getAndSet(false);
+ }
@@ -250,6 +260,8 @@ index 0000000000000000000000000000000000000000..dc5a5f42c9ca7a50295c18424722568a
+ save();
+ } catch (IOException e) {
+ LOGGER.error("Failed to flush region file " + path.toAbsolutePath(), e);
+ }finally {
+ this.dirtyChunkCount.set(0); //Reset dirty chunk count
+ }
+ }
+
@@ -333,8 +345,11 @@ index 0000000000000000000000000000000000000000..dc5a5f42c9ca7a50295c18424722568a
+ this.bufferUncompressedSize[getChunkIndex(pos.x, pos.z)] = uncompressedSize;
+ } catch (IOException e) {
+ LOGGER.error("Chunk write IOException " + e + " " + this.path);
+ }finally {
+ this.dirtyChunkCount.getAndIncrement();
+ }
+ markToSave();
+ signalToSave();
+ }
+
+ public DataOutputStream getChunkDataOutputStream(ChunkPos pos) {
@@ -386,7 +401,9 @@ index 0000000000000000000000000000000000000000..dc5a5f42c9ca7a50295c18424722568a
+ this.buffer[i] = null;
+ this.bufferUncompressedSize[i] = 0;
+ this.chunkTimestamps[i] = getTimestamp();
+ this.dirtyChunkCount.getAndIncrement();
+ markToSave();
+ signalToSave();
+ }
+
+ public boolean hasChunk(ChunkPos pos) {
@@ -423,22 +440,19 @@ index 0000000000000000000000000000000000000000..dc5a5f42c9ca7a50295c18424722568a
+}
diff --git a/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFileFlusher.java b/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFileFlusher.java
new file mode 100644
index 0000000000000000000000000000000000000000..65435eb666b2e1cabffc145e016faa5e3b373464
index 0000000000000000000000000000000000000000..dea4dffd67ee9881a224acf41367c6845acec832
--- /dev/null
+++ b/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFileFlusher.java
@@ -0,0 +1,57 @@
@@ -0,0 +1,63 @@
+package dev.kaiijumc.kaiiju.region;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
+import java.util.Set;
+import java.util.concurrent.*;
+import org.bukkit.Bukkit;
+
+public class LinearRegionFileFlusher {
+ private final Set<LinearRegionFile> pendingSaving = ConcurrentHashMap.newKeySet();
+
+ private final ExecutorService executor = Executors.newFixedThreadPool(
+ private final ExecutorService ioExecutor = Executors.newFixedThreadPool(
+ me.earthme.luminol.config.modules.misc.RegionFormatConfig.linearFlushThreads,
+ new ThreadFactoryBuilder()
+ .setNameFormat("linear-flusher-%d")
@@ -448,7 +462,7 @@ index 0000000000000000000000000000000000000000..65435eb666b2e1cabffc145e016faa5e
+ private final Executor delayedFlusher = CompletableFuture.delayedExecutor(
+ me.earthme.luminol.config.modules.misc.RegionFormatConfig.linearFlushFrequency,
+ TimeUnit.SECONDS,
+ executor
+ ioExecutor
+ );
+
+ public LinearRegionFileFlusher() {
@@ -456,28 +470,37 @@ index 0000000000000000000000000000000000000000..65435eb666b2e1cabffc145e016faa5e
+ }
+
+ public void scheduleSave(LinearRegionFile regionFile) {
+ if (this.pendingSaving.contains(regionFile) || !regionFile.isMarkedToSave()){
+ if (regionFile.dirtyChunkCount.get() > me.earthme.luminol.config.modules.misc.RegionFormatConfig.flushImmediatelyIfDirtyChunkHigherThan){
+ this.scheduleSaveInternal(regionFile,this.ioExecutor);
+ return;
+ }
+
+ this.pendingSaving.add(regionFile);
+ this.delayedFlusher.execute(()->{
+ this.scheduleSaveInternal(regionFile,this.delayedFlusher);
+ }
+
+ private void scheduleSaveInternal(LinearRegionFile regionFile,Executor scheduler){
+ if (!regionFile.savingScheduled || !regionFile.isMarkedToSave()){
+ return;
+ }
+
+ regionFile.savingScheduled = true;
+ scheduler.execute(()->{
+ try {
+ if (!regionFile.closed && regionFile.isMarkedToSave()){
+ regionFile.flushWrapper();
+ }
+ }finally {
+ regionFile.resetSaveMarker();
+ this.pendingSaving.remove(regionFile);
+ regionFile.savingScheduled = false;
+ }
+ });
+ }
+
+ public void shutdown() {
+ this.executor.shutdown();
+ this.ioExecutor.shutdown();
+ for (;;) {
+ try {
+ if (this.executor.awaitTermination(5_00,TimeUnit.MILLISECONDS)) break;
+ if (this.ioExecutor.awaitTermination(5_00,TimeUnit.MILLISECONDS)) break;
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
@@ -573,6 +596,18 @@ index 2934f0cf0ef09c84739312b00186c2ef0019a165..b46acbc078f3d3bfb0f3ede3f1cc172f
}
}
}
diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionShutdownThread.java b/src/main/java/io/papermc/paper/threadedregions/RegionShutdownThread.java
index 3f3fd8b1881106f893ffb677272e50d77cbb6626..338dfc1c87ac82df80b3b87148deb791110ce3cc 100644
--- a/src/main/java/io/papermc/paper/threadedregions/RegionShutdownThread.java
+++ b/src/main/java/io/papermc/paper/threadedregions/RegionShutdownThread.java
@@ -164,6 +164,7 @@ public final class RegionShutdownThread extends TickThread {
this.saveLevelData(world);
}
+ dev.kaiijumc.kaiiju.region.LinearRegionFile.linearRegionFileFlusher.shutdown(); //Luminol - Kaiiju linear format fixes
// moved from stop part 1
// we need this to be after saving level data, as that will complete any teleportations the player is in
LOGGER.info("Saving players");
diff --git a/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java b/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java
index 9017907c0ec67a37a506f09b7e4499cef7885279..8b9ffcaab5d71660291d1c0454d2abd969d8c6ae 100644
--- a/src/main/java/io/papermc/paper/world/ThreadedWorldUpgrader.java
@@ -594,10 +629,10 @@ index 9017907c0ec67a37a506f09b7e4499cef7885279..8b9ffcaab5d71660291d1c0454d2abd9
diff --git a/src/main/java/me/earthme/luminol/config/modules/misc/RegionFormatConfig.java b/src/main/java/me/earthme/luminol/config/modules/misc/RegionFormatConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..5d594b606178bd26180caad49de17c0e67e89747
index 0000000000000000000000000000000000000000..ab1c3e0276bbdbb32fd4155f7c596f3172c7f351
--- /dev/null
+++ b/src/main/java/me/earthme/luminol/config/modules/misc/RegionFormatConfig.java
@@ -0,0 +1,58 @@
@@ -0,0 +1,60 @@
+package me.earthme.luminol.config.modules.misc;
+
+import com.electronwill.nightconfig.core.file.CommentedFileConfig;
@@ -620,6 +655,8 @@ index 0000000000000000000000000000000000000000..5d594b606178bd26180caad49de17c0e
+ @HotReloadUnsupported
+ @ConfigInfo(baseName = "linear_flush_frequency")
+ public static int linearFlushFrequency = 10;
+ @ConfigInfo(baseName = "flush_immediately_if_queued_higher_than")
+ public static int flushImmediatelyIfDirtyChunkHigherThan = 5;
+
+ @Override
+ public EnumConfigCategory getCategory() {