From b31223e24ab08dad22207bb738bee9b44d845246 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Sun, 26 May 2024 09:12:26 -0700 Subject: [PATCH] Extract chunk system threads to general common threads This allows us to use them for chunk rendering, which should reduce competition between the background executor pool and the chunk system for cpu resources. --- .../common/config/PlaceholderConfig.java | 3 +- .../moonrise/common/util/MoonriseCommon.java | 48 +++++++++++++++++++ .../mixin/chunk_system/ServerLevelMixin.java | 3 +- .../render/SectionRenderDispatcherMixin.java | 44 +++++++++++++++++ .../scheduling/ChunkTaskScheduler.java | 36 ++------------ src/main/resources/moonrise.mixins.json | 1 + 6 files changed, 101 insertions(+), 34 deletions(-) create mode 100644 src/main/java/ca/spottedleaf/moonrise/common/util/MoonriseCommon.java create mode 100644 src/main/java/ca/spottedleaf/moonrise/mixin/render/SectionRenderDispatcherMixin.java diff --git a/src/main/java/ca/spottedleaf/moonrise/common/config/PlaceholderConfig.java b/src/main/java/ca/spottedleaf/moonrise/common/config/PlaceholderConfig.java index 5188ed9..a556b6b 100644 --- a/src/main/java/ca/spottedleaf/moonrise/common/config/PlaceholderConfig.java +++ b/src/main/java/ca/spottedleaf/moonrise/common/config/PlaceholderConfig.java @@ -13,8 +13,9 @@ public final class PlaceholderConfig { public static int autoSaveInterval = 60 * 5 * 20; // 5 mins public static int maxAutoSaveChunksPerTick = 12; + public static int workerThreads = -1; + public static int chunkSystemIOThreads = -1; - public static int chunkSystemThreads = -1; public static String chunkSystemGenParallelism = "default"; } diff --git a/src/main/java/ca/spottedleaf/moonrise/common/util/MoonriseCommon.java b/src/main/java/ca/spottedleaf/moonrise/common/util/MoonriseCommon.java new file mode 100644 index 0000000..6f03c2c --- /dev/null +++ b/src/main/java/ca/spottedleaf/moonrise/common/util/MoonriseCommon.java @@ -0,0 +1,48 @@ +package ca.spottedleaf.moonrise.common.util; + +import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedThreadPool; +import ca.spottedleaf.moonrise.common.config.PlaceholderConfig; +import ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class MoonriseCommon { + + private static final Logger LOGGER = LoggerFactory.getLogger(ChunkTaskScheduler.class); + + public static final PrioritisedThreadPool WORKER_POOL; + public static final int WORKER_THREADS; + static { + int defaultWorkerThreads = Runtime.getRuntime().availableProcessors() / 2; + if (defaultWorkerThreads <= 4) { + defaultWorkerThreads = defaultWorkerThreads <= 3 ? 1 : 2; + } else { + defaultWorkerThreads = defaultWorkerThreads / 2; + } + defaultWorkerThreads = Integer.getInteger("Moonrise.WorkerThreadCount", Integer.valueOf(defaultWorkerThreads)); + + int workerThreads = PlaceholderConfig.workerThreads; + + if (workerThreads < 0) { + workerThreads = defaultWorkerThreads; + } else { + workerThreads = Math.max(1, workerThreads); + } + + WORKER_POOL = new PrioritisedThreadPool( + "Moonrise Chunk System Worker Pool", workerThreads, + (final Thread thread, final Integer id) -> { + thread.setName("Moonrise Chunk System Worker #" + id.intValue()); + thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { + @Override + public void uncaughtException(final Thread thread, final Throwable throwable) { + LOGGER.error("Uncaught exception in thread " + thread.getName(), throwable); + } + }); + }, (long)(20.0e6)); // 20ms + WORKER_THREADS = workerThreads; + } + + private MoonriseCommon() {} + +} diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ServerLevelMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ServerLevelMixin.java index ac9beed..65bbade 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ServerLevelMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/chunk_system/ServerLevelMixin.java @@ -2,6 +2,7 @@ package ca.spottedleaf.moonrise.mixin.chunk_system; import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor; import ca.spottedleaf.moonrise.common.util.CoordinateUtils; +import ca.spottedleaf.moonrise.common.util.MoonriseCommon; import ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread; import ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.ChunkDataController; import ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.EntityDataController; @@ -117,7 +118,7 @@ public abstract class ServerLevelMixin extends Level implements ChunkSystemServe this.poiDataController = new PoiDataController((ServerLevel)(Object)this); this.chunkDataController = new ChunkDataController((ServerLevel)(Object)this); this.moonrise$setEntityLookup(new ServerEntityLookup((ServerLevel)(Object)this, ((ServerLevel)(Object)this).new EntityCallbacks())); - this.chunkTaskScheduler = new ChunkTaskScheduler((ServerLevel)(Object)this, ChunkTaskScheduler.workerThreads); + this.chunkTaskScheduler = new ChunkTaskScheduler((ServerLevel)(Object)this, MoonriseCommon.WORKER_POOL); } @Override diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/render/SectionRenderDispatcherMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/render/SectionRenderDispatcherMixin.java new file mode 100644 index 0000000..ec1a9d8 --- /dev/null +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/render/SectionRenderDispatcherMixin.java @@ -0,0 +1,44 @@ +package ca.spottedleaf.moonrise.mixin.render; + +import ca.spottedleaf.concurrentutil.executor.standard.PrioritisedExecutor; +import ca.spottedleaf.moonrise.common.util.MoonriseCommon; +import net.minecraft.client.renderer.chunk.SectionRenderDispatcher; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.function.Supplier; + +@Mixin(SectionRenderDispatcher.class) +public abstract class SectionRenderDispatcherMixin { + + @Unique + private static final PrioritisedExecutor RENDER_EXECUTOR = MoonriseCommon.WORKER_POOL.createExecutor( + "Moonrise Render Executor", 1, MoonriseCommon.WORKER_THREADS + ); + + /** + * @reason Change executor to use our thread pool + * Note: even at normal priority, our worker pool will try to share resources equally rather than having it + * be a free-for-all + * @author Spottedleaf + */ + @Redirect( + method = "runTask", + at = @At( + value = "INVOKE", + target = "Ljava/util/concurrent/CompletableFuture;supplyAsync(Ljava/util/function/Supplier;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;" + ) + ) + private CompletableFuture changeExecutor(final Supplier supplier, final Executor executor) { + return CompletableFuture.supplyAsync( + supplier, + (final Runnable task) -> { + RENDER_EXECUTOR.queueRunnable(task, PrioritisedExecutor.Priority.NORMAL); + } + ); + } + +} diff --git a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java index 20cc91a..32fc6ae 100644 --- a/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java +++ b/src/main/java/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ChunkTaskScheduler.java @@ -7,6 +7,7 @@ import ca.spottedleaf.concurrentutil.lock.ReentrantAreaLock; import ca.spottedleaf.concurrentutil.util.ConcurrentUtil; import ca.spottedleaf.moonrise.common.config.PlaceholderConfig; import ca.spottedleaf.moonrise.common.util.CoordinateUtils; +import ca.spottedleaf.moonrise.common.util.MoonriseCommon; import ca.spottedleaf.moonrise.common.util.TickThread; import ca.spottedleaf.moonrise.common.util.WorldUtil; import ca.spottedleaf.moonrise.patches.chunk_system.io.RegionFileIOThread; @@ -49,12 +50,9 @@ public final class ChunkTaskScheduler { private static final Logger LOGGER = LoggerFactory.getLogger(ChunkTaskScheduler.class); static int newChunkSystemIOThreads; - static int newChunkSystemWorkerThreads; static int newChunkSystemGenParallelism; static int newChunkSystemLoadParallelism; - public static PrioritisedThreadPool workerThreads; - private static boolean initialised = false; public static void init() { @@ -63,25 +61,11 @@ public final class ChunkTaskScheduler { } initialised = true; newChunkSystemIOThreads = PlaceholderConfig.chunkSystemIOThreads; - newChunkSystemWorkerThreads = PlaceholderConfig.chunkSystemThreads; if (newChunkSystemIOThreads < 0) { newChunkSystemIOThreads = 1; } else { newChunkSystemIOThreads = Math.max(1, newChunkSystemIOThreads); } - int defaultWorkerThreads = Runtime.getRuntime().availableProcessors() / 2; - if (defaultWorkerThreads <= 4) { - defaultWorkerThreads = defaultWorkerThreads <= 3 ? 1 : 2; - } else { - defaultWorkerThreads = defaultWorkerThreads / 2; - } - defaultWorkerThreads = Integer.getInteger("Moonrise.WorkerThreadCount", Integer.valueOf(defaultWorkerThreads)); - - if (newChunkSystemWorkerThreads < 0) { - newChunkSystemWorkerThreads = defaultWorkerThreads; - } else { - newChunkSystemWorkerThreads = Math.max(1, newChunkSystemWorkerThreads); - } String newChunkSystemGenParallelism = PlaceholderConfig.chunkSystemGenParallelism; if (newChunkSystemGenParallelism.equalsIgnoreCase("default")) { @@ -98,24 +82,12 @@ public final class ChunkTaskScheduler { throw new IllegalStateException("Invalid option for gen-parallelism: must be one of [on, off, enabled, disabled, true, false, default]"); } - ChunkTaskScheduler.newChunkSystemGenParallelism = useParallelGen ? newChunkSystemWorkerThreads : 1; - ChunkTaskScheduler.newChunkSystemLoadParallelism = newChunkSystemWorkerThreads; + ChunkTaskScheduler.newChunkSystemGenParallelism = useParallelGen ? MoonriseCommon.WORKER_THREADS : 1; + ChunkTaskScheduler.newChunkSystemLoadParallelism = MoonriseCommon.WORKER_THREADS; RegionFileIOThread.init(newChunkSystemIOThreads); - workerThreads = new PrioritisedThreadPool( - "Paper Chunk System Worker Pool", newChunkSystemWorkerThreads, - (final Thread thread, final Integer id) -> { - thread.setPriority(Thread.NORM_PRIORITY - 2); - thread.setName("Moonrise Chunk System Worker #" + id.intValue()); - thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { - @Override - public void uncaughtException(final Thread thread, final Throwable throwable) { - LOGGER.error("Uncaught exception in thread " + thread.getName(), throwable); - } - }); - }, (long)(20.0e6)); // 20ms - LOGGER.info("Chunk system is using " + newChunkSystemIOThreads + " I/O threads, " + newChunkSystemWorkerThreads + " worker threads, and gen parallelism of " + ChunkTaskScheduler.newChunkSystemGenParallelism + " threads"); + LOGGER.info("Chunk system is using " + newChunkSystemIOThreads + " I/O threads, " + MoonriseCommon.WORKER_THREADS + " worker threads, and gen parallelism of " + ChunkTaskScheduler.newChunkSystemGenParallelism + " threads"); } public static final TicketType CHUNK_LOAD = TicketType.create("chunk_system:chunk_load", Long::compareTo); diff --git a/src/main/resources/moonrise.mixins.json b/src/main/resources/moonrise.mixins.json index 28dcf86..a4d7aa9 100644 --- a/src/main/resources/moonrise.mixins.json +++ b/src/main/resources/moonrise.mixins.json @@ -97,6 +97,7 @@ "chunk_system.OptionsMixin", "collisions.LiquidBlockRendererMixin", "collisions.ParticleMixin", + "render.SectionRenderDispatcherMixin", "serverlist.ClientConnectionMixin", "serverlist.ServerSelectionListMixin", "starlight.multiplayer.ClientPacketListenerMixin"