aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0745-Do-not-submit-profile-lookups-to-worldgen-threads.patch
blob: 534570379cd08344f4d56de14424ebd790282d41 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
index 5bdd1958dff2fc9321bf858e6aa4cc5ad0a5a9ca..354e8096d404bfca8055aafcd80b2de29a7bc929 100644
--- a/src/main/java/net/minecraft/Util.java
+++ b/src/main/java/net/minecraft/Util.java
@@ -76,6 +76,22 @@ public class Util {
     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) -> {
+                LOGGER.fatal("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();
     public static LongSupplier timeSource = System::nanoTime;
     public static final UUID NIL_UUID = new UUID(0L, 0L);
diff --git a/src/main/java/net/minecraft/server/players/GameProfileCache.java b/src/main/java/net/minecraft/server/players/GameProfileCache.java
index a157f71cf55b9e97fac56c7c55b552da86000fd5..4e2833dc941863cc54416c81f09c688b5616d7a4 100644
--- a/src/main/java/net/minecraft/server/players/GameProfileCache.java
+++ b/src/main/java/net/minecraft/server/players/GameProfileCache.java
@@ -200,7 +200,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 e3efea8623c7d34915069a6b9b7da9f2b1694c28..118472b83a21a250f398c088c91ac4560c19c749 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
@@ -148,7 +148,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) {