2021-08-26 02:16:27 +00:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Sun, 8 Aug 2021 16:26:46 -0700
Subject: [PATCH] Do not submit profile lookups to worldgen threads
They block. On network I/O.
If enough tasks are submitted the server will eventually stall
out due to a sync load, as the worldgen threads will be
stalling on profile lookups.
diff --git a/src/main/java/net/minecraft/Util.java b/src/main/java/net/minecraft/Util.java
2022-06-08 10:20:57 +00:00
index 5f9e3d37c3ba79d26806374d73f87328cebb562d..206c6ce227ba19620185ac835af28d67caa76c40 100644
2021-08-26 02:16:27 +00:00
--- a/src/main/java/net/minecraft/Util.java
+++ b/src/main/java/net/minecraft/Util.java
2022-06-08 10:20:57 +00:00
@@ -80,6 +80,22 @@ public class Util {
2021-08-26 02:16:27 +00:00
private static final AtomicInteger WORKER_COUNT = new AtomicInteger(1);
private static final ExecutorService BOOTSTRAP_EXECUTOR = makeExecutor("Bootstrap", -2); // Paper - add -2 priority
private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main", -1); // Paper - add -1 priority
+ // 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) -> {
2022-02-28 22:02:20 +00:00
+ LOGGER.error("Uncaught exception in thread " + thread.getName(), throwable);
2021-08-26 02:16:27 +00:00
+ });
+ return ret;
+ }
+ });
+ // Paper end - don't submit BLOCKING PROFILE LOOKUPS to the world gen thread
private static final ExecutorService IO_POOL = makeIoExecutor();
public static LongSupplier timeSource = System::nanoTime;
2022-03-01 05:43:03 +00:00
public static final Ticker TICKER = new Ticker() {
2021-08-26 02:16:27 +00:00
diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java
2022-06-08 10:20:57 +00:00
index 2097d9eef58eb291c9055189fc3da6222ab8429f..1c5dfd2aa50118fcd2a451472873975d75a8e327 100644
2021-08-26 02:16:27 +00:00
--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java
+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java
2022-03-18 02:44:45 +00:00
@@ -206,7 +206,7 @@ public class GameProfileCache {
2021-08-26 02:16:27 +00:00
} else {
this.requests.put(username, CompletableFuture.supplyAsync(() -> {
return this.get(username);
- }, Util.backgroundExecutor()).whenCompleteAsync((optional, throwable) -> {
+ }, Util.PROFILE_EXECUTOR).whenCompleteAsync((optional, throwable) -> { // Paper - not a good idea to use BLOCKING OPERATIONS on the worldgen executor
this.requests.remove(username);
}, this.executor).whenCompleteAsync((optional, throwable) -> {
consumer.accept(optional);
diff --git a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java
2022-06-08 10:20:57 +00:00
index 170f051d820ee1add1b61a20dbd1f18f758717dc..c1703a67a615f563dab4fb442a6df7082229af57 100644
2021-08-26 02:16:27 +00:00
--- a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java
+++ b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java
2022-06-08 10:20:57 +00:00
@@ -149,7 +149,7 @@ public class SkullBlockEntity extends BlockEntity {
2021-08-26 02:16:27 +00:00
public static void updateGameprofile(@Nullable GameProfile owner, Consumer<GameProfile> callback) {
if (owner != null && !StringUtil.isNullOrEmpty(owner.getName()) && (!owner.isComplete() || !owner.getProperties().containsKey("textures")) && profileCache != null && sessionService != null) {
profileCache.getAsync(owner.getName(), (profile) -> {
- Util.backgroundExecutor().execute(() -> {
+ Util.PROFILE_EXECUTOR.execute(() -> { // Paper - not a good idea to use BLOCKING OPERATIONS on the worldgen executor
Util.ifElse(profile, (profilex) -> {
Property property = Iterables.getFirst(profilex.getProperties().get("textures"), (Property)null);
if (property == null) {