Skip to content

Commit

Permalink
Extract chunk system threads to general common threads
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Spottedleaf committed May 26, 2024
1 parent 1d60cdb commit b31223e
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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";

}
Original file line number Diff line number Diff line change
@@ -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() {}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

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;
Expand Down Expand Up @@ -117,7 +118,7 @@ private void init(MinecraftServer minecraftServer, Executor executor,
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
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
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;
Expand Down Expand Up @@ -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() {
Expand All @@ -63,25 +61,11 @@ public static void init() {
}
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")) {
Expand All @@ -98,24 +82,12 @@ public static void init() {
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);
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/moonrise.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
"chunk_system.OptionsMixin",
"collisions.LiquidBlockRendererMixin",
"collisions.ParticleMixin",
"render.SectionRenderDispatcherMixin",
"serverlist.ClientConnectionMixin",
"serverlist.ServerSelectionListMixin",
"starlight.multiplayer.ClientPacketListenerMixin"
Expand Down

0 comments on commit b31223e

Please sign in to comment.