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"