mirror of
https://github.com/Dreeam-qwq/Gale.git
synced 2025-12-22 08:19:31 +00:00
232 lines
12 KiB
Diff
232 lines
12 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Martijn Muijsers <martijnmuijsers@live.nl>
|
|
Date: Sun, 29 Jan 2023 22:37:12 +0100
|
|
Subject: [PATCH] Run chunk cache tasks on base thread pool
|
|
|
|
License: AGPL-3.0 (https://www.gnu.org/licenses/agpl-3.0.html)
|
|
Gale - https://galemc.org
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
index 83a57b9bc59063ed8299f98bc33e14b57f2ea0de..5187fd95577afa4ddf4544206ec6bb467bcdce81 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
@@ -11,7 +11,6 @@ import java.util.Collections;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
-import java.util.Optional;
|
|
import java.util.concurrent.CompletableFuture;
|
|
import java.util.concurrent.Executor;
|
|
import java.util.function.BooleanSupplier;
|
|
@@ -22,6 +21,7 @@ import net.minecraft.Util;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.SectionPos;
|
|
import net.minecraft.network.protocol.Packet;
|
|
+import net.minecraft.server.MinecraftServer;
|
|
import net.minecraft.server.level.progress.ChunkProgressListener;
|
|
import net.minecraft.util.VisibleForDebug;
|
|
import net.minecraft.util.thread.BlockableEventLoop;
|
|
@@ -446,7 +446,7 @@ public class ServerChunkCache extends ChunkSource {
|
|
// Paper end
|
|
com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.level, x1, z1); // Paper - sync load info
|
|
this.level.timings.syncChunkLoad.startTiming(); // Paper
|
|
- chunkproviderserver_b.managedBlock(completablefuture::isDone);
|
|
+ chunkproviderserver_b.managedYield(completablefuture); // Gale - base thread pool
|
|
io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.popChunkWait(); // Paper - async chunk debug // Paper - rewrite chunk system
|
|
this.level.timings.syncChunkLoad.stopTiming(); // Paper
|
|
} // Paper
|
|
@@ -489,7 +489,7 @@ public class ServerChunkCache extends ChunkSource {
|
|
ServerChunkCache.MainThreadExecutor chunkproviderserver_b = this.mainThreadProcessor;
|
|
|
|
Objects.requireNonNull(completablefuture);
|
|
- chunkproviderserver_b.managedBlock(completablefuture::isDone);
|
|
+ chunkproviderserver_b.managedYield(completablefuture); // Gale - base thread pool
|
|
} else {
|
|
completablefuture = CompletableFuture.supplyAsync(() -> {
|
|
return this.getChunkFutureMainThread(chunkX, chunkZ, leastStatus, create);
|
|
@@ -973,6 +973,15 @@ public class ServerChunkCache extends ChunkSource {
|
|
|
|
public final class MainThreadExecutor extends BlockableEventLoop<Runnable> {
|
|
|
|
+ // Gale start - base thread pool
|
|
+ /**
|
|
+ * The time interval for the server thread to yield when this executor is performing
|
|
+ * a {@link #managedYield} but failed to perform any other tasks from this executor itself.
|
|
+ */
|
|
+ private static final long MANAGED_YIELD_TIMEOUT_TIME = 50_000L;
|
|
+ private static @Nullable YieldingLock yieldingLockToNotifyForNewChunkCacheTasks;
|
|
+ // Gale end - base thread pool
|
|
+
|
|
MainThreadExecutor(Level world) {
|
|
super("Chunk source main thread executor for " + world.dimension().location());
|
|
}
|
|
@@ -1002,6 +1011,40 @@ public class ServerChunkCache extends ChunkSource {
|
|
super.doRunTask(task);
|
|
}
|
|
|
|
+ // Gale start - base thread pool
|
|
+ @Override
|
|
+ public void tell(Runnable runnable) {
|
|
+ super.tell(runnable);
|
|
+ MinecraftServer.nextTimeAssumeWeMayHaveDelayedTasks = true;
|
|
+ BaseTaskQueues.allLevelsScheduledChunkCache.newTaskWasAdded();
|
|
+ if (yieldingLockToNotifyForNewChunkCacheTasks != null) {
|
|
+ yieldingLockToNotifyForNewChunkCacheTasks.unlock();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public void managedBlock(BooleanSupplier stopCondition) {
|
|
+ throw new UnsupportedOperationException("Cannot call " + this.getClass().getName() + ".managedBlock(BooleanSupplier), call managedYield(CompletableFuture) instead");
|
|
+ }
|
|
+
|
|
+ public void managedYield(CompletableFuture<?> future) {
|
|
+ if (!future.isDone()) {
|
|
+ ++this.blockingCount;
|
|
+ try {
|
|
+ var currentThread = AbstractYieldingThread.currentYieldingThread();
|
|
+ while (!future.isDone()) {
|
|
+ if (!this.pollTask()) {
|
|
+ long timeoutTime = System.nanoTime() + MANAGED_YIELD_TIMEOUT_TIME;
|
|
+ currentThread.yieldUntilFuture(timeoutTime, () -> this.hasPendingTasks(), future, autoCompletingLock -> yieldingLockToNotifyForNewChunkCacheTasks = autoCompletingLock);
|
|
+ }
|
|
+ }
|
|
+ yieldingLockToNotifyForNewChunkCacheTasks = null;
|
|
+ } finally {
|
|
+ --this.blockingCount;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ // Gale end - base thread pool
|
|
+
|
|
@Override
|
|
// CraftBukkit start - process pending Chunk loadCallback() and unloadCallback() after each run task
|
|
public boolean pollTask() {
|
|
diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java
|
|
index 392e7b4a89669f16b32043b65b69e6593d17f10e..6328c0254b585b3bc169dd2b5d0f25bfd67566d2 100644
|
|
--- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java
|
|
+++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java
|
|
@@ -21,7 +21,7 @@ public abstract class BlockableEventLoop<R extends Runnable> implements Profiler
|
|
private final String name;
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
private final Queue<R> pendingRunnables = Queues.newConcurrentLinkedQueue();
|
|
- private int blockingCount;
|
|
+ protected int blockingCount; // Gale - base thread pool
|
|
|
|
protected BlockableEventLoop(String name) {
|
|
this.name = name;
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
index 949feba1264bcafb8dc2dcecd0a566fea80a2ba0..9eae3862abb5f1d7755a8e777fd4bf9a6f8e321d 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
|
|
@@ -470,7 +470,7 @@ public class CraftWorld extends CraftRegionAccessor implements World {
|
|
list,
|
|
true
|
|
);
|
|
- serverChunkCache.mainThreadProcessor.managedBlock(future::isDone);
|
|
+ serverChunkCache.mainThreadProcessor.managedYield(future); // Gale - base thread pool
|
|
if (chunkStatus == ChunkStatus.NOISE) {
|
|
future.join().left().ifPresent(chunk -> net.minecraft.world.level.levelgen.Heightmap.primeHeightmaps(chunk, ChunkStatus.POST_FEATURES));
|
|
}
|
|
diff --git a/src/main/java/org/galemc/gale/executor/queue/AllLevelsScheduledChunkCacheTaskQueue.java b/src/main/java/org/galemc/gale/executor/queue/AllLevelsScheduledChunkCacheTaskQueue.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..fe2e06a827555d81a30697f8b08667692a3eeade
|
|
--- /dev/null
|
|
+++ b/src/main/java/org/galemc/gale/executor/queue/AllLevelsScheduledChunkCacheTaskQueue.java
|
|
@@ -0,0 +1,52 @@
|
|
+// Gale - base thread pool
|
|
+
|
|
+package org.galemc.gale.executor.queue;
|
|
+
|
|
+import net.minecraft.server.MinecraftServer;
|
|
+import net.minecraft.server.level.ServerChunkCache;
|
|
+import net.minecraft.server.level.ServerLevel;
|
|
+import org.galemc.gale.executor.TaskSpan;
|
|
+import org.galemc.gale.executor.annotation.thread.AnyThreadSafe;
|
|
+import org.galemc.gale.executor.annotation.YieldFree;
|
|
+import org.galemc.gale.executor.thread.ServerThread;
|
|
+import org.jetbrains.annotations.Nullable;
|
|
+
|
|
+/**
|
|
+ * This class provides access to, but does not store, the tasks scheduled to be executed on the main thread,
|
|
+ * that are scheduled and normally polled by each world's {@link ServerChunkCache#mainThreadProcessor} in their
|
|
+ * respective {@link ServerChunkCache.MainThreadExecutor#managedBlock}. These tasks could normally also be run in the
|
|
+ * server's {@link MinecraftServer#managedBlock} if there were no more global scheduled server thread tasks, and as
|
|
+ * such we provide access to polling these tasks from a {@link ServerThread}.
|
|
+ * <br>
|
|
+ * All tasks provided by this queue must be yield-free.
|
|
+ *
|
|
+ * @author Martijn Muijsers under AGPL-3.0
|
|
+ */
|
|
+@AnyThreadSafe
|
|
+@YieldFree
|
|
+public final class AllLevelsScheduledChunkCacheTaskQueue extends AllLevelsScheduledTaskQueue {
|
|
+
|
|
+ AllLevelsScheduledChunkCacheTaskQueue() {
|
|
+ super(TaskSpan.YIELDING, false);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public String getName() {
|
|
+ return "AllLevelsScheduledChunkCache";
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected boolean hasLevelTasks(ServerLevel level) {
|
|
+ return level.getChunkSource().mainThreadProcessor.hasPendingTasks();
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected @Nullable Runnable pollLevel(ServerLevel level) {
|
|
+ var executor = level.getChunkSource().mainThreadProcessor;
|
|
+ if (executor.hasPendingTasks()) {
|
|
+ return executor::pollTask;
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/org/galemc/gale/executor/queue/AllLevelsScheduledTaskQueue.java b/src/main/java/org/galemc/gale/executor/queue/AllLevelsScheduledTaskQueue.java
|
|
index 657c3663ed54043e7e4e6660d34903ef746fd8e7..c2acd36b3101042f39afe1436836078dcce2100d 100644
|
|
--- a/src/main/java/org/galemc/gale/executor/queue/AllLevelsScheduledTaskQueue.java
|
|
+++ b/src/main/java/org/galemc/gale/executor/queue/AllLevelsScheduledTaskQueue.java
|
|
@@ -12,7 +12,8 @@ import org.galemc.gale.executor.thread.pool.BaseThreadActivation;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
/**
|
|
- * Common implementation for queues with scheduled tasks for all levels.
|
|
+ * Common implementation for queues with scheduled tasks for all levels,
|
|
+ * such as {@link AllLevelsScheduledChunkCacheTaskQueue}.
|
|
* <br>
|
|
* All tasks provided by this queue must be yield-free.
|
|
*
|
|
diff --git a/src/main/java/org/galemc/gale/executor/queue/BaseTaskQueueTier.java b/src/main/java/org/galemc/gale/executor/queue/BaseTaskQueueTier.java
|
|
index f4adcdcad96b2748c60aecb8f5c25370ee6e8f5b..8465ce8de44d823aac4784fbc5183b9fc49b2825 100644
|
|
--- a/src/main/java/org/galemc/gale/executor/queue/BaseTaskQueueTier.java
|
|
+++ b/src/main/java/org/galemc/gale/executor/queue/BaseTaskQueueTier.java
|
|
@@ -61,7 +61,8 @@ public enum BaseTaskQueueTier {
|
|
SERVER(new AbstractTaskQueue[]{
|
|
BaseTaskQueues.deferredToServerThread,
|
|
BaseTaskQueues.serverThreadTick,
|
|
- BaseTaskQueues.anyTickScheduledServerThread
|
|
+ BaseTaskQueues.anyTickScheduledServerThread,
|
|
+ BaseTaskQueues.allLevelsScheduledChunkCache
|
|
}, MinecraftServer.SERVER_THREAD_PRIORITY),
|
|
/**
|
|
* A tier for queues that contain tasks that are part of ticking,
|
|
diff --git a/src/main/java/org/galemc/gale/executor/queue/BaseTaskQueues.java b/src/main/java/org/galemc/gale/executor/queue/BaseTaskQueues.java
|
|
index 92721a51268becb05d708db04e9d6daaa66fb8b2..c608cdfc17e02a37e8f1799af2b26f973a32c839 100644
|
|
--- a/src/main/java/org/galemc/gale/executor/queue/BaseTaskQueues.java
|
|
+++ b/src/main/java/org/galemc/gale/executor/queue/BaseTaskQueues.java
|
|
@@ -90,6 +90,11 @@ public final class BaseTaskQueues {
|
|
*/
|
|
public static final SimpleTaskQueue tickAssist = SimpleTaskQueue.allSpans("TickAssist");
|
|
|
|
+ /**
|
|
+ * @see AllLevelsScheduledChunkCacheTaskQueue
|
|
+ */
|
|
+ public static final AllLevelsScheduledChunkCacheTaskQueue allLevelsScheduledChunkCache = new AllLevelsScheduledChunkCacheTaskQueue();
|
|
+
|
|
/**
|
|
* This queue stores the tasks posted to {@link MCUtil#cleanerExecutor}.
|
|
*/
|