--- a/net/minecraft/Util.java +++ b/net/minecraft/Util.java @@ -92,9 +92,25 @@ 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 + public static final ExecutorService PROFILE_EXECUTOR = Executors.newFixedThreadPool(2, new java.util.concurrent.ThreadFactory() { + + private final AtomicInteger count = new AtomicInteger(); + + @Override + public Thread newThread(Runnable run) { + Thread ret = new Thread(run); + ret.setName("Profile Lookup Executor #" + this.count.getAndIncrement()); + ret.setUncaughtExceptionHandler((Thread thread, Throwable throwable) -> { + LOGGER.error("Uncaught exception in thread " + thread.getName(), throwable); + }); + return ret; + } + }); + // Paper end - don't submit BLOCKING PROFILE LOOKUPS to the world gen thread private static final DateTimeFormatter FILENAME_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss", Locale.ROOT); public static final int LINEAR_LOOKUP_THRESHOLD = 8; private static final Set ALLOWED_UNTRUSTED_LINK_PROTOCOLS = Set.of("http", "https"); @@ -136,7 +152,7 @@ } public static long getNanos() { - return timeSource.getAsLong(); + return System.nanoTime(); // Paper } public static long getEpochMillis() { @@ -147,15 +163,16 @@ return FILENAME_DATE_TIME_FORMATTER.format(ZonedDateTime.now()); } - private static TracingExecutor makeExecutor(String name) { + private static TracingExecutor makeExecutor(String name, final int priorityModifier) { // Paper - Perf: add priority int i = maxAllowedExecutorThreads(); - ExecutorService executorService; + // Paper start - Perf: use simpler thread pool that allows 1 thread and reduce worldgen thread worker count for low core count CPUs + final 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, name, priorityModifier)); + } + /* final String string2 = "Worker-" + name + "-" + atomicInteger.getAndIncrement(); ForkJoinWorkerThread forkJoinWorkerThread = new ForkJoinWorkerThread(pool) { @Override protected void onStart() { @@ -177,13 +194,26 @@ forkJoinWorkerThread.setName(string2); return forkJoinWorkerThread; }, Util::onThreadException, true); - } + }*/ return new TracingExecutor(executorService); } public static int maxAllowedExecutorThreads() { - return Mth.clamp(Runtime.getRuntime().availableProcessors() - 1, 1, getMaxThreads()); + // Paper start - Perf: use simpler thread pool that allows 1 thread and reduce worldgen thread worker count for low core count CPUs + final int cpus = Runtime.getRuntime().availableProcessors() / 2; + int maxExecutorThreads; + if (cpus <= 4) { + maxExecutorThreads = cpus <= 2 ? 1 : 2; + } else if (cpus <= 8) { + // [5, 8] + maxExecutorThreads = Math.max(3, cpus - 2); + } else { + maxExecutorThreads = cpus * 2 / 3; + } + maxExecutorThreads = Math.min(8, maxExecutorThreads); + return Integer.getInteger("Paper.WorkerThreadCount", maxExecutorThreads); + // Paper end - Perf: use simpler thread pool that allows 1 thread and reduce worldgen thread worker count for low core count CPUs } private static int getMaxThreads() { @@ -537,7 +567,7 @@ public static , V> EnumMap makeEnumMap(Class enumClass, Function mapper) { EnumMap enumMap = new EnumMap<>(enumClass); - for (K enum_ : (Enum[])enumClass.getEnumConstants()) { + for (K enum_ : enumClass.getEnumConstants()) { // Paper - decompile error enumMap.put(enum_, mapper.apply(enum_)); } @@ -1057,16 +1087,7 @@ } public void openUri(URI uri) { - try { - Process process = AccessController.doPrivileged( - (PrivilegedExceptionAction)(() -> Runtime.getRuntime().exec(this.getOpenUriArguments(uri))) - ); - process.getInputStream().close(); - process.getErrorStream().close(); - process.getOutputStream().close(); - } catch (IOException | PrivilegedActionException var3) { - Util.LOGGER.error("Couldn't open location '{}'", uri, var3); - } + throw new IllegalStateException("This method is not useful on dedicated servers."); // Paper - Fix warnings on build by removing client-only code } public void openFile(File file) {