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.
This commit is contained in:
Spottedleaf
2024-05-26 09:12:26 -07:00
parent 1d60cdb400
commit b31223e24a
6 changed files with 101 additions and 34 deletions

View File

@@ -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";
}

View File

@@ -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() {}
}

View File

@@ -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

View File

@@ -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 <U> CompletableFuture<U> changeExecutor(final Supplier<U> supplier, final Executor executor) {
return CompletableFuture.supplyAsync(
supplier,
(final Runnable task) -> {
RENDER_EXECUTOR.queueRunnable(task, PrioritisedExecutor.Priority.NORMAL);
}
);
}
}

View File

@@ -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<Long> CHUNK_LOAD = TicketType.create("chunk_system:chunk_load", Long::compareTo);

View File

@@ -97,6 +97,7 @@
"chunk_system.OptionsMixin",
"collisions.LiquidBlockRendererMixin",
"collisions.ParticleMixin",
"render.SectionRenderDispatcherMixin",
"serverlist.ClientConnectionMixin",
"serverlist.ServerSelectionListMixin",
"starlight.multiplayer.ClientPacketListenerMixin"