aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0140-Do-not-submit-profile-lookups-to-worldgen-threads.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/server/0140-Do-not-submit-profile-lookups-to-worldgen-threads.patch')
-rw-r--r--patches/server/0140-Do-not-submit-profile-lookups-to-worldgen-threads.patch77
1 files changed, 77 insertions, 0 deletions
diff --git a/patches/server/0140-Do-not-submit-profile-lookups-to-worldgen-threads.patch b/patches/server/0140-Do-not-submit-profile-lookups-to-worldgen-threads.patch
new file mode 100644
index 0000000000..b2385e0d42
--- /dev/null
+++ b/patches/server/0140-Do-not-submit-profile-lookups-to-worldgen-threads.patch
@@ -0,0 +1,77 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Spottedleaf <[email protected]>
+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 168ab805ecc48dd55db90eb7fe1c56fda3f2776c..336a26733b5bf73455f8ec10347c1e08b8e866f7 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 376845f5a25a348e76193fac5c047b0ba2fb080f..2a0cf0a8a79c09566c598197fc6f8c447d4bbd72 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 0c7e29b589ab106013d979a20edc415b4b32a677..c5d5d90d10b30f30d1262367b3d75df43fbdb231 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
+@@ -120,7 +120,7 @@ public class SkullBlockEntity extends BlockEntity {
+ 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) {
+diff --git a/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java b/src/main/java/org/bukkit/craftbukkit/profile/CraftPlayerProfile.java
+index 2d49bd6f3f017d43dfaa23cedf35040b64bcdcf8..9edc5e73819e0b55372f77c5e292eece74d837c7 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<PlayerProfile> 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() {