9
0
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:
Dreeam
2024-04-01 01:28:14 -04:00
parent d59542c369
commit c7b3e4ea96
12 changed files with 134 additions and 18 deletions

View File

@@ -704,10 +704,10 @@ index f6338904ca0961cfd67326908e9cf72e37c6e86e..21c15670c0c9b988472ac8e875a1c033
public boolean alwaysTameInCreative = false; 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 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 new file mode 100644
index 0000000000000000000000000000000000000000..e6ab1ca9a699c3f57855f2acc8d08b8a005bce2f index 0000000000000000000000000000000000000000..4f903d384959e4353ac1b310b9a70beeb2ce7f6a
--- /dev/null --- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/region/AbstractRegionFile.java +++ b/src/main/java/org/purpurmc/purpur/region/AbstractRegionFile.java
@@ -0,0 +1,31 @@ @@ -0,0 +1,43 @@
+package org.purpurmc.purpur.region; +package org.purpurmc.purpur.region;
+ +
+import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.CompoundTag;
@@ -722,21 +722,33 @@ index 0000000000000000000000000000000000000000..e6ab1ca9a699c3f57855f2acc8d08b8a
+ +
+public interface AbstractRegionFile { +public interface AbstractRegionFile {
+ void flush() throws IOException; + void flush() throws IOException;
+
+ void clear(ChunkPos pos) throws IOException; + void clear(ChunkPos pos) throws IOException;
+
+ void close() throws IOException; + void close() throws IOException;
+
+ void setStatus(int x, int z, ChunkStatus status); + void setStatus(int x, int z, ChunkStatus status);
+
+ void setOversized(int x, int z, boolean b) throws IOException; + void setOversized(int x, int z, boolean b) throws IOException;
+ +
+ boolean hasChunk(ChunkPos pos); + boolean hasChunk(ChunkPos pos);
+
+ boolean doesChunkExist(ChunkPos pos) throws Exception; + boolean doesChunkExist(ChunkPos pos) throws Exception;
+
+ boolean isOversized(int x, int z); + boolean isOversized(int x, int z);
+
+ boolean recalculateHeader() throws IOException; + boolean recalculateHeader() throws IOException;
+ +
+ DataOutputStream getChunkDataOutputStream(ChunkPos pos) throws IOException; + DataOutputStream getChunkDataOutputStream(ChunkPos pos) throws IOException;
+
+ DataInputStream getChunkDataInputStream(ChunkPos pos) throws IOException; + DataInputStream getChunkDataInputStream(ChunkPos pos) throws IOException;
+
+ CompoundTag getOversizedData(int x, int z) throws IOException; + CompoundTag getOversizedData(int x, int z) throws IOException;
+
+ ChunkStatus getStatusIfCached(int x, int z); + ChunkStatus getStatusIfCached(int x, int z);
+
+ ReentrantLock getFileLock(); + ReentrantLock getFileLock();
+
+ Path getRegionFile(); + Path getRegionFile();
+} +}
diff --git a/src/main/java/org/purpurmc/purpur/region/AbstractRegionFileFactory.java b/src/main/java/org/purpurmc/purpur/region/AbstractRegionFileFactory.java 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 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 new file mode 100644
index 0000000000000000000000000000000000000000..731a90436cae2e615c228c07f042fa112b95a8d2 index 0000000000000000000000000000000000000000..041f97f32beabc52400f57d056de3d4d313d3e74
--- /dev/null --- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/region/LinearRegionFile.java +++ b/src/main/java/org/purpurmc/purpur/region/LinearRegionFile.java
@@ -0,0 +1,316 @@ @@ -0,0 +1,317 @@
+package org.purpurmc.purpur.region; +package org.purpurmc.purpur.region;
+ +
+import com.github.luben.zstd.ZstdInputStream; +import com.github.luben.zstd.ZstdInputStream;
@@ -1044,7 +1056,7 @@ index 0000000000000000000000000000000000000000..731a90436cae2e615c228c07f042fa11
+ +
+ @Nullable + @Nullable
+ public synchronized DataInputStream getChunkDataInputStream(ChunkPos pos) { + 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)]]; + 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)]); + 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)); + return new DataInputStream(new ByteArrayInputStream(content));
@@ -1086,7 +1098,8 @@ index 0000000000000000000000000000000000000000..731a90436cae2e615c228c07f042fa11
+ return false; + 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 { + public CompoundTag getOversizedData(int x, int z) throws IOException {
+ throw new IOException("getOversizedData is a stub " + this.path); + 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 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 new file mode 100644
index 0000000000000000000000000000000000000000..60f8ed586676609b9be7626eebf865aaaee92ac2 index 0000000000000000000000000000000000000000..0d3d9193e8d8f72141dc155840c5eed1a744761c
--- /dev/null --- /dev/null
+++ b/src/main/java/org/purpurmc/purpur/region/LinearRegionFileFlusher.java +++ b/src/main/java/org/purpurmc/purpur/region/LinearRegionFileFlusher.java
@@ -0,0 +1,45 @@ @@ -0,0 +1,50 @@
+package org.purpurmc.purpur.region; +package org.purpurmc.purpur.region;
+ +
+import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
+import java.util.Queue; +import java.util.Queue;
+import java.util.concurrent.*; +import java.util.concurrent.*;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.purpurmc.purpur.PurpurConfig; +import org.purpurmc.purpur.PurpurConfig;
+import org.bukkit.Bukkit; +import org.bukkit.Bukkit;
+ +
+public class LinearRegionFileFlusher { +public class LinearRegionFileFlusher {
+ private final Logger LOGGER = LogManager.getLogger(getClass().getName());
+ private final Queue<LinearRegionFile> savingQueue = new LinkedBlockingQueue<>(); + private final Queue<LinearRegionFile> savingQueue = new LinkedBlockingQueue<>();
+ private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor( + private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(
+ new ThreadFactoryBuilder() + new ThreadFactoryBuilder()
+ .setNameFormat("linear-flush-scheduler") + .setNameFormat("linear-flush-scheduler")
+ .build() + .build()
+ ); + );
+ private final ExecutorService executor = Executors.newFixedThreadPool( + private final ExecutorService executor = Executors.newFixedThreadPool(
+ PurpurConfig.linearFlushThreads, + PurpurConfig.linearFlushThreads,
+ new ThreadFactoryBuilder() + new ThreadFactoryBuilder()
+ .setNameFormat("linear-flusher-%d") + .setNameFormat("linear-flusher-%d")
+ .build() + .build()
+ ); + );
+ +
+ public LinearRegionFileFlusher() { + public LinearRegionFileFlusher() {

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: nostalfinals <yuu8583@proton.me> From: nostalfinals <yuu8583@proton.me>
Date: Tue, 12 Mar 2024 00:36:29 +0800 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 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.FormattingTuple");
tryPreloadClass("org.slf4j.helpers.BasicMarker"); 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 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 --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftAsyncScheduler.java
+++ b/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.destroystokyo.paper.ServerSchedulerReportingWrapper;
import com.google.common.util.concurrent.ThreadFactoryBuilder; 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.galemc.gale.virtualthread.VirtualThreadService;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
@@ -43,6 +45,7 @@ index 9c1aff17aabd062640e3f451a2ef8c50a7c62f10..3f119f51e1af89f63be00f5a54a98143
- private final ThreadPoolExecutor executor = new ThreadPoolExecutor( - private final ThreadPoolExecutor executor = new ThreadPoolExecutor(
- 4, Integer.MAX_VALUE,30L, TimeUnit.SECONDS, new SynchronousQueue<>(), - 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 - 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 Executor executor; // Leaf - use super class
private final Executor management = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder() 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 .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) { + if (VirtualThreadService.getJavaMajorVersion() >= VirtualThreadService.minimumJavaMajorVersionWithoutFeaturePreview && org.dreeam.leaf.config.modules.opt.VT4BukkitScheduler.enabled) {
+ try { + try {
+ Method newThreadPerTaskExecutor = Executors.class.getMethod("newThreadPerTaskExecutor", ThreadFactory.class); + Method newThreadPerTaskExecutor = Executors.class.getMethod("newThreadPerTaskExecutor", ThreadFactory.class);
+
+ executor = (Executor) newThreadPerTaskExecutor.invoke(null, VirtualThreadService.get().createFactory()); + executor = (Executor) newThreadPerTaskExecutor.invoke(null, VirtualThreadService.get().createFactory());
+ //executor = Executors.newThreadPerTaskExecutor(Thread.ofVirtual().name("Craft Scheduler Thread - ", 0).factory()); // Leaf - When Minecraft using Java21 + //executor = Executors.newThreadPerTaskExecutor(Thread.ofVirtual().name("Craft Scheduler Thread - ", 0).factory()); // Leaf - When Minecraft using Java21
+ return; + return;
+ } catch (Exception ignored) { + } catch (Exception ignored) {
+ LOGGER.error("Failed to create Virtual Thread executor! Fallback to default executor.");
+ } + }
+ } + }
+ +

View 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.");