From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Spottedleaf 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 index 4423140df56e64527db470ada17a117656b93114..c085ed233eb4d1f2100ec23a77447ef799ecdf1f 100644 --- a/src/main/java/net/minecraft/Util.java +++ b/src/main/java/net/minecraft/Util.java @@ -81,6 +81,22 @@ public class Util { private static final AtomicInteger WORKER_COUNT = new AtomicInteger(1); private static final ExecutorService BOOTSTRAP_EXECUTOR = makeExecutor("Bootstrap"); private static final ExecutorService BACKGROUND_EXECUTOR = makeExecutor("Main"); + // 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 ExecutorService IO_POOL = makeIoExecutor(); private static final DateTimeFormatter FILENAME_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss", Locale.ROOT); public static TimeSource.NanoTimeSource timeSource = System::nanoTime; diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java index 58e923f4ef1980bc7fff1e3b3fcdaad8c4eded53..4038bb76339d43f18770624bd7fecc79b8d7f2a9 100644 --- a/src/main/java/net/minecraft/server/players/GameProfileCache.java +++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java @@ -181,7 +181,7 @@ public class GameProfileCache { } 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 index 8fa6b788c4c330ad50e9833bbf7082da540b109c..91fb6678214d5f23b33d5d3b65a29fdfbb003c58 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/SkullBlockEntity.java @@ -137,7 +137,7 @@ public class SkullBlockEntity extends BlockEntity { public static void updateGameprofile(@Nullable GameProfile owner, Consumer 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) { diff --git a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java b/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java index 3030c153725415802f68c144e0b577d919307058..3e40d47f504248cd7caeef6b841a8aa6f1976170 100644 --- a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java +++ b/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java @@ -121,7 +121,7 @@ public final class CraftPlayerProfile implements PlayerProfile { @Override public CompletableFuture update() { - return CompletableFuture.supplyAsync(this::getUpdatedProfile, Util.backgroundExecutor()); + return CompletableFuture.supplyAsync(this::getUpdatedProfile, Util.PROFILE_EXECUTOR); // Paper - not a good idea to use BLOCKING OPERATIONS on the worldgen executor } private CraftPlayerProfile getUpdatedProfile() {