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.

diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
         S s0 = function.apply(thread); // CraftBukkit - decompile error
 
         atomicreference.set(s0);
+        thread.setPriority(Thread.NORM_PRIORITY+2); // Paper - boost priority
         thread.start();
         return s0;
     }
diff --git a/src/main/java/net/minecraft/server/ServerWorkerThread.java b/src/main/java/net/minecraft/server/ServerWorkerThread.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
+++ b/src/main/java/net/minecraft/server/ServerWorkerThread.java
@@ -0,0 +0,0 @@
+package net.minecraft.server;
+
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class ServerWorkerThread extends Thread {
+    private static final AtomicInteger threadId = new AtomicInteger(1);
+    public ServerWorkerThread(Runnable target) {
+        super(target, "Server-Worker-" + threadId.getAndIncrement());
+        setPriority(Thread.NORM_PRIORITY-1); // Deprioritize over main
+        this.setUncaughtExceptionHandler((thread, throwable) -> {
+            if (throwable instanceof CompletionException) {
+                throwable = throwable.getCause();
+            }
+
+            if (throwable instanceof ReportedException) {
+                DispenserRegistry.a(((ReportedException) throwable).a().e());
+                System.exit(-1);
+            }
+
+            MinecraftServer.LOGGER.error(String.format("Caught exception in thread %s", thread), throwable);
+        });
+    }
+}
diff --git a/src/main/java/net/minecraft/server/SystemUtils.java b/src/main/java/net/minecraft/server/SystemUtils.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/SystemUtils.java
+++ b/src/main/java/net/minecraft/server/SystemUtils.java
@@ -0,0 +0,0 @@ public class SystemUtils {
     }
 
     private static ExecutorService a(String s) {
-        int i = MathHelper.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, 7);
-        Object object;
+        // Paper start - use simpler thread pool that allows 1 thread
+        int i = Math.min(8, Math.max(Runtime.getRuntime().availableProcessors() - 2, 1));
+        i = Integer.getInteger("Paper.WorkerThreadCount", i);
+        ExecutorService object;
 
         if (i <= 0) {
             object = MoreExecutors.newDirectExecutorService();
         } else {
-            object = new ForkJoinPool(i, (forkjoinpool) -> {
-                ForkJoinWorkerThread forkjoinworkerthread = new ForkJoinWorkerThread(forkjoinpool) {
+            object = new java.util.concurrent.ThreadPoolExecutor(i, i,0L, TimeUnit.MILLISECONDS, new java.util.concurrent.LinkedBlockingQueue<Runnable>(), ServerWorkerThread::new);
+        }
+        /*
                     protected void onTermination(Throwable throwable) {
                         if (throwable != null) {
                             SystemUtils.LOGGER.warn("{} died", this.getName(), throwable);
@@ -0,0 +0,0 @@ public class SystemUtils {
                 return forkjoinworkerthread;
             }, SystemUtils::a, true);
         }
+        }*/ // Paper end
 
         return (ExecutorService) object;
     }
