mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-22 00:19:20 +00:00
Add ability to use Virtual Thread for Linear region flusher
This commit is contained in:
@@ -704,10 +704,10 @@ index f6338904ca0961cfd67326908e9cf72e37c6e86e..21c15670c0c9b988472ac8e875a1c033
|
||||
public boolean alwaysTameInCreative = false;
|
||||
diff --git a/src/main/java/org/purpurmc/purpur/region/AbstractRegionFile.java b/src/main/java/org/purpurmc/purpur/region/AbstractRegionFile.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e6ab1ca9a699c3f57855f2acc8d08b8a005bce2f
|
||||
index 0000000000000000000000000000000000000000..4f903d384959e4353ac1b310b9a70beeb2ce7f6a
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/purpurmc/purpur/region/AbstractRegionFile.java
|
||||
@@ -0,0 +1,31 @@
|
||||
@@ -0,0 +1,43 @@
|
||||
+package org.purpurmc.purpur.region;
|
||||
+
|
||||
+import net.minecraft.nbt.CompoundTag;
|
||||
@@ -722,21 +722,33 @@ index 0000000000000000000000000000000000000000..e6ab1ca9a699c3f57855f2acc8d08b8a
|
||||
+
|
||||
+public interface AbstractRegionFile {
|
||||
+ void flush() throws IOException;
|
||||
+
|
||||
+ void clear(ChunkPos pos) throws IOException;
|
||||
+
|
||||
+ void close() throws IOException;
|
||||
+
|
||||
+ void setStatus(int x, int z, ChunkStatus status);
|
||||
+
|
||||
+ void setOversized(int x, int z, boolean b) throws IOException;
|
||||
+
|
||||
+ boolean hasChunk(ChunkPos pos);
|
||||
+
|
||||
+ boolean doesChunkExist(ChunkPos pos) throws Exception;
|
||||
+
|
||||
+ boolean isOversized(int x, int z);
|
||||
+
|
||||
+ boolean recalculateHeader() throws IOException;
|
||||
+
|
||||
+ DataOutputStream getChunkDataOutputStream(ChunkPos pos) throws IOException;
|
||||
+
|
||||
+ DataInputStream getChunkDataInputStream(ChunkPos pos) throws IOException;
|
||||
+
|
||||
+ CompoundTag getOversizedData(int x, int z) throws IOException;
|
||||
+
|
||||
+ ChunkStatus getStatusIfCached(int x, int z);
|
||||
+
|
||||
+ ReentrantLock getFileLock();
|
||||
+
|
||||
+ Path getRegionFile();
|
||||
+}
|
||||
diff --git a/src/main/java/org/purpurmc/purpur/region/AbstractRegionFileFactory.java b/src/main/java/org/purpurmc/purpur/region/AbstractRegionFileFactory.java
|
||||
@@ -776,10 +788,10 @@ index 0000000000000000000000000000000000000000..c88ff6fda185a8489cbefa51a7b09ccb
|
||||
+}
|
||||
diff --git a/src/main/java/org/purpurmc/purpur/region/LinearRegionFile.java b/src/main/java/org/purpurmc/purpur/region/LinearRegionFile.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..731a90436cae2e615c228c07f042fa112b95a8d2
|
||||
index 0000000000000000000000000000000000000000..041f97f32beabc52400f57d056de3d4d313d3e74
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/purpurmc/purpur/region/LinearRegionFile.java
|
||||
@@ -0,0 +1,316 @@
|
||||
@@ -0,0 +1,317 @@
|
||||
+package org.purpurmc.purpur.region;
|
||||
+
|
||||
+import com.github.luben.zstd.ZstdInputStream;
|
||||
@@ -1044,7 +1056,7 @@ index 0000000000000000000000000000000000000000..731a90436cae2e615c228c07f042fa11
|
||||
+
|
||||
+ @Nullable
|
||||
+ public synchronized DataInputStream getChunkDataInputStream(ChunkPos pos) {
|
||||
+ if(this.bufferUncompressedSize[getChunkIndex(pos.x, pos.z)] != 0) {
|
||||
+ if (this.bufferUncompressedSize[getChunkIndex(pos.x, pos.z)] != 0) {
|
||||
+ byte[] content = new byte[bufferUncompressedSize[getChunkIndex(pos.x, pos.z)]];
|
||||
+ this.decompressor.decompress(this.buffer[getChunkIndex(pos.x, pos.z)], 0, content, 0, bufferUncompressedSize[getChunkIndex(pos.x, pos.z)]);
|
||||
+ return new DataInputStream(new ByteArrayInputStream(content));
|
||||
@@ -1086,7 +1098,8 @@ index 0000000000000000000000000000000000000000..731a90436cae2e615c228c07f042fa11
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ public void setOversized(int x, int z, boolean something) {}
|
||||
+ public void setOversized(int x, int z, boolean something) {
|
||||
+ }
|
||||
+
|
||||
+ public CompoundTag getOversizedData(int x, int z) throws IOException {
|
||||
+ throw new IOException("getOversizedData is a stub " + this.path);
|
||||
@@ -1098,30 +1111,35 @@ index 0000000000000000000000000000000000000000..731a90436cae2e615c228c07f042fa11
|
||||
+}
|
||||
diff --git a/src/main/java/org/purpurmc/purpur/region/LinearRegionFileFlusher.java b/src/main/java/org/purpurmc/purpur/region/LinearRegionFileFlusher.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..60f8ed586676609b9be7626eebf865aaaee92ac2
|
||||
index 0000000000000000000000000000000000000000..0d3d9193e8d8f72141dc155840c5eed1a744761c
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/purpurmc/purpur/region/LinearRegionFileFlusher.java
|
||||
@@ -0,0 +1,45 @@
|
||||
@@ -0,0 +1,50 @@
|
||||
+package org.purpurmc.purpur.region;
|
||||
+
|
||||
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
+
|
||||
+import java.util.Queue;
|
||||
+import java.util.concurrent.*;
|
||||
+
|
||||
+import org.apache.logging.log4j.LogManager;
|
||||
+import org.apache.logging.log4j.Logger;
|
||||
+import org.purpurmc.purpur.PurpurConfig;
|
||||
+import org.bukkit.Bukkit;
|
||||
+
|
||||
+public class LinearRegionFileFlusher {
|
||||
+ private final Logger LOGGER = LogManager.getLogger(getClass().getName());
|
||||
+ private final Queue<LinearRegionFile> savingQueue = new LinkedBlockingQueue<>();
|
||||
+ private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(
|
||||
+ new ThreadFactoryBuilder()
|
||||
+ .setNameFormat("linear-flush-scheduler")
|
||||
+ .build()
|
||||
+ new ThreadFactoryBuilder()
|
||||
+ .setNameFormat("linear-flush-scheduler")
|
||||
+ .build()
|
||||
+ );
|
||||
+ private final ExecutorService executor = Executors.newFixedThreadPool(
|
||||
+ PurpurConfig.linearFlushThreads,
|
||||
+ new ThreadFactoryBuilder()
|
||||
+ .setNameFormat("linear-flusher-%d")
|
||||
+ .build()
|
||||
+ PurpurConfig.linearFlushThreads,
|
||||
+ new ThreadFactoryBuilder()
|
||||
+ .setNameFormat("linear-flusher-%d")
|
||||
+ .build()
|
||||
+ );
|
||||
+
|
||||
+ public LinearRegionFileFlusher() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: nostalfinals <yuu8583@proton.me>
|
||||
Date: Tue, 12 Mar 2024 00:36:29 +0800
|
||||
Subject: [PATCH] Ability to use Virtual Thread for async scheduler
|
||||
Subject: [PATCH] Virtual Thread for async scheduler
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
|
||||
@@ -17,13 +17,15 @@ index ee166ad76bd2c143e04e4bf6bd9991bc90ab99a5..13f3f8628143ffc22a2d2c2129ea4836
|
||||
tryPreloadClass("org.slf4j.helpers.FormattingTuple");
|
||||
tryPreloadClass("org.slf4j.helpers.BasicMarker");
|
||||
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java
|
||||
index 9c1aff17aabd062640e3f451a2ef8c50a7c62f10..3f119f51e1af89f63be00f5a54a9814358f04be6 100644
|
||||
index 9c1aff17aabd062640e3f451a2ef8c50a7c62f10..ba7784780a578350992be3e2cfcb9791aa805838 100644
|
||||
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java
|
||||
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java
|
||||
@@ -25,30 +25,50 @@ package org.bukkit.craftbukkit.scheduler;
|
||||
@@ -25,30 +25,55 @@ package org.bukkit.craftbukkit.scheduler;
|
||||
|
||||
import com.destroystokyo.paper.ServerSchedulerReportingWrapper;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
+import org.apache.logging.log4j.LogManager;
|
||||
+import org.apache.logging.log4j.Logger;
|
||||
+import org.galemc.gale.virtualthread.VirtualThreadService;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
@@ -43,6 +45,7 @@ index 9c1aff17aabd062640e3f451a2ef8c50a7c62f10..3f119f51e1af89f63be00f5a54a98143
|
||||
- private final ThreadPoolExecutor executor = new ThreadPoolExecutor(
|
||||
- 4, Integer.MAX_VALUE,30L, TimeUnit.SECONDS, new SynchronousQueue<>(),
|
||||
- new ThreadFactoryBuilder().setNameFormat("Craft Scheduler Thread - %1$d").setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(net.minecraft.server.MinecraftServer.LOGGER)).build()); // Paper
|
||||
+ private final Logger LOGGER = LogManager.getLogger(getClass().getName()); // Leaf - Class logger
|
||||
+ private Executor executor; // Leaf - use super class
|
||||
private final Executor management = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder()
|
||||
.setNameFormat("Craft Async Scheduler Management Thread").setUncaughtExceptionHandler(new net.minecraft.DefaultUncaughtExceptionHandlerWithName(net.minecraft.server.MinecraftServer.LOGGER)).build()); // Paper
|
||||
@@ -57,10 +60,12 @@ index 9c1aff17aabd062640e3f451a2ef8c50a7c62f10..3f119f51e1af89f63be00f5a54a98143
|
||||
+ if (VirtualThreadService.getJavaMajorVersion() >= VirtualThreadService.minimumJavaMajorVersionWithoutFeaturePreview && org.dreeam.leaf.config.modules.opt.VT4BukkitScheduler.enabled) {
|
||||
+ try {
|
||||
+ Method newThreadPerTaskExecutor = Executors.class.getMethod("newThreadPerTaskExecutor", ThreadFactory.class);
|
||||
+
|
||||
+ executor = (Executor) newThreadPerTaskExecutor.invoke(null, VirtualThreadService.get().createFactory());
|
||||
+ //executor = Executors.newThreadPerTaskExecutor(Thread.ofVirtual().name("Craft Scheduler Thread - ", 0).factory()); // Leaf - When Minecraft using Java21
|
||||
+ return;
|
||||
+ } catch (Exception ignored) {
|
||||
+ LOGGER.error("Failed to create Virtual Thread executor! Fallback to default executor.");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
93
patches/server/0076-Virtual-Thread-for-linear-flusher.patch
Normal file
93
patches/server/0076-Virtual-Thread-for-linear-flusher.patch
Normal file
@@ -0,0 +1,93 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Radiation_pi <pi1243039811@outlook.com>
|
||||
Date: Mon, 25 Mar 2024 23:00:19 +0800
|
||||
Subject: [PATCH] Virtual Thread for linear flusher
|
||||
|
||||
|
||||
diff --git a/src/main/java/org/dreeam/leaf/config/modules/opt/VT4LinearFlusher.java b/src/main/java/org/dreeam/leaf/config/modules/opt/VT4LinearFlusher.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..d4576c9930d12548d4302207f61a0eb8b1fa7b7a
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/org/dreeam/leaf/config/modules/opt/VT4LinearFlusher.java
|
||||
@@ -0,0 +1,29 @@
|
||||
+package org.dreeam.leaf.config.modules.opt;
|
||||
+
|
||||
+import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||
+import org.dreeam.leaf.config.ConfigInfo;
|
||||
+import org.dreeam.leaf.config.EnumConfigCategory;
|
||||
+import org.dreeam.leaf.config.IConfigModule;
|
||||
+
|
||||
+public class VT4LinearFlusher implements IConfigModule {
|
||||
+
|
||||
+ @Override
|
||||
+ public EnumConfigCategory getCategory() {
|
||||
+ return EnumConfigCategory.PERFORMANCE;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public String getBaseName() {
|
||||
+ return "use_virtual_thread_for_linear_flusher";
|
||||
+ }
|
||||
+
|
||||
+ @ConfigInfo(baseName = "enabled")
|
||||
+ public static boolean enabled = false;
|
||||
+
|
||||
+ @Override
|
||||
+ public void onLoaded(CommentedFileConfig config) {
|
||||
+ config.setComment("performance.use_virtual_thread_for_linear_flusher", """
|
||||
+ Use the new Virtual Thread introduced in JDK 21 for Linear Region Flusher.
|
||||
+ """);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/org/purpurmc/purpur/region/LinearRegionFileFlusher.java b/src/main/java/org/purpurmc/purpur/region/LinearRegionFileFlusher.java
|
||||
index 0d3d9193e8d8f72141dc155840c5eed1a744761c..339157b5e5a81e3c1c5b54fbd9e3c53ea3f51716 100644
|
||||
--- a/src/main/java/org/purpurmc/purpur/region/LinearRegionFileFlusher.java
|
||||
+++ b/src/main/java/org/purpurmc/purpur/region/LinearRegionFileFlusher.java
|
||||
@@ -4,9 +4,12 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.*;
|
||||
+import java.lang.reflect.InvocationTargetException;
|
||||
+import java.lang.reflect.Method;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
+import org.galemc.gale.virtualthread.VirtualThreadService;
|
||||
import org.purpurmc.purpur.PurpurConfig;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
@@ -18,12 +21,28 @@ public class LinearRegionFileFlusher {
|
||||
.setNameFormat("linear-flush-scheduler")
|
||||
.build()
|
||||
);
|
||||
- private final ExecutorService executor = Executors.newFixedThreadPool(
|
||||
- PurpurConfig.linearFlushThreads,
|
||||
- new ThreadFactoryBuilder()
|
||||
- .setNameFormat("linear-flusher-%d")
|
||||
- .build()
|
||||
- );
|
||||
+
|
||||
+ private ExecutorService executor;
|
||||
+
|
||||
+ {
|
||||
+ try {
|
||||
+ if (VirtualThreadService.getJavaMajorVersion() >= VirtualThreadService.minimumJavaMajorVersionWithoutFeaturePreview && org.dreeam.leaf.config.modules.opt.VT4LinearFlusher.enabled) {
|
||||
+ Method newThreadPerTaskExecutor = Executors.class.getMethod("newThreadPerTaskExecutor", ThreadFactory.class);
|
||||
+
|
||||
+ executor = (ExecutorService) newThreadPerTaskExecutor.invoke(null, VirtualThreadService.get().createFactory());
|
||||
+ } else {
|
||||
+ throw new UnsupportedOperationException();
|
||||
+ }
|
||||
+ } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException |
|
||||
+ UnsupportedOperationException e) {
|
||||
+ LOGGER.error("Failed to create Virtual Thread executor! Fallback to default executor.");
|
||||
+ executor = Executors.newFixedThreadPool(
|
||||
+ PurpurConfig.linearFlushThreads,
|
||||
+ new ThreadFactoryBuilder()
|
||||
+ .setNameFormat("linear-flusher-%d")
|
||||
+ .build());
|
||||
+ }
|
||||
+ }
|
||||
|
||||
public LinearRegionFileFlusher() {
|
||||
Bukkit.getLogger().info("Using " + PurpurConfig.linearFlushThreads + " threads for linear region flushing.");
|
||||
Reference in New Issue
Block a user