PaperMC/patches/server/0259-Improve-Server-Thread-Pool-and-Thread-Priorities.patch
Nassim Jahnke 64828f3a60
Clean up thread pool usage (#11681)
Using an unbound LinkedBlockingQueue means you *have* to set core and max core thread pool size the same, as they will never go above the minimum pool size by just passing them through. So this fixes the async command executor pool to actually use 2 threads, and also cleans up other usage to be explicitly "fixed" thread pool sizes, and splits off one more in Minecraft's Util class
2024-11-29 17:07:35 +01:00

107 lines
5.4 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Tue, 23 Oct 2018 23:14:38 -0400
Subject: [PATCH] Improve Server Thread Pool and Thread Priorities
Use a simple executor since Fork join is a much more complex pool
type and we are not using its capabilities.
Set thread priorities so main thread has above normal priority over
server threads
Allow usage of a single thread executor by not using ForkJoin so single core CPU's
and reduce worldgen thread worker count for low core count CPUs.
== AT ==
public net.minecraft.Util onThreadException(Ljava/lang/Thread;Ljava/lang/Throwable;)V
Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com>
diff --git a/src/main/java/io/papermc/paper/util/ServerWorkerThread.java b/src/main/java/io/papermc/paper/util/ServerWorkerThread.java
new file mode 100644
index 0000000000000000000000000000000000000000..b60f59cf5cc8eb84a6055b7861857dece7f2501b
--- /dev/null
+++ b/src/main/java/io/papermc/paper/util/ServerWorkerThread.java
@@ -0,0 +1,14 @@
+package io.papermc.paper.util;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import net.minecraft.Util;
+
+public class ServerWorkerThread extends Thread {
+ private static final AtomicInteger threadId = new AtomicInteger(1);
+ public ServerWorkerThread(Runnable target, String poolName, int prioritityModifier) {
+ super(target, "Worker-" + poolName + "-" + threadId.getAndIncrement());
+ setPriority(Thread.NORM_PRIORITY+prioritityModifier); // Deprioritize over main
+ this.setDaemon(true);
+ this.setUncaughtExceptionHandler(Util::onThreadException);
+ }
+}
diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java
index 8cac2075077b1d9c2b01e09c99780ff9e204abb2..dbf79a018260a006bf5d16608b35bcbea9adb963 100644
--- a/src/main/java/net/minecraft/Util.java
+++ b/src/main/java/net/minecraft/Util.java
@@ -92,7 +92,7 @@ public class Util {
private static final int DEFAULT_MAX_THREADS = 255;
private static final int DEFAULT_SAFE_FILE_OPERATION_RETRIES = 10;
private static final String MAX_THREADS_SYSTEM_PROPERTY = "max.bg.threads";
- private static final TracingExecutor BACKGROUND_EXECUTOR = makeExecutor("Main");
+ private static final TracingExecutor BACKGROUND_EXECUTOR = makeExecutor("Main", -1); // Paper - Perf: add priority
private static final TracingExecutor IO_POOL = makeIoExecutor("IO-Worker-", false);
private static final TracingExecutor DOWNLOAD_POOL = makeIoExecutor("Download-", true);
// Paper start - don't submit BLOCKING PROFILE LOOKUPS to the world gen thread
@@ -163,15 +163,28 @@ public class Util {
return FILENAME_DATE_TIME_FORMATTER.format(ZonedDateTime.now());
}
- private static TracingExecutor makeExecutor(String name) {
- int i = Mth.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, getMaxThreads());
+ private static TracingExecutor makeExecutor(String s, final int priorityModifier) { // Paper - Perf: add priority
+ // Paper start - Perf: use simpler thread pool that allows 1 thread and reduce worldgen thread worker count for low core count CPUs
+ int cpus = Runtime.getRuntime().availableProcessors() / 2;
+ int i;
+ if (cpus <= 4) {
+ i = cpus <= 2 ? 1 : 2;
+ } else if (cpus <= 8) {
+ // [5, 8]
+ i = Math.max(3, cpus - 2);
+ } else {
+ i = cpus * 2 / 3;
+ }
+ i = Math.min(8, i);
+ i = Integer.getInteger("Paper.WorkerThreadCount", i);
+
ExecutorService executorService;
if (i <= 0) {
executorService = MoreExecutors.newDirectExecutorService();
} else {
- AtomicInteger atomicInteger = new AtomicInteger(1);
- executorService = new ForkJoinPool(i, pool -> {
- final String string2 = "Worker-" + name + "-" + atomicInteger.getAndIncrement();
+ executorService = Executors.newFixedThreadPool(i, target -> new io.papermc.paper.util.ServerWorkerThread(target, s, priorityModifier));
+ }
+ /* final String string2 = "Worker-" + name + "-" + atomicInteger.getAndIncrement();
ForkJoinWorkerThread forkJoinWorkerThread = new ForkJoinWorkerThread(pool) {
@Override
protected void onStart() {
@@ -193,7 +206,7 @@ public class Util {
forkJoinWorkerThread.setName(string2);
return forkJoinWorkerThread;
}, Util::onThreadException, true);
- }
+ }*/
return new TracingExecutor(executorService);
}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index af20a16e18673a629fc3033d8e7e07eba855b1c7..2a4f8075867a302afd98bdf9ac8b11622c29082d 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -332,6 +332,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
thread.setUncaughtExceptionHandler((thread1, throwable) -> {
MinecraftServer.LOGGER.error("Uncaught exception in server thread", throwable);
});
+ thread.setPriority(Thread.NORM_PRIORITY+2); // Paper - Perf: Boost priority
if (Runtime.getRuntime().availableProcessors() > 4) {
thread.setPriority(8);
}