mirror of
https://github.com/PaperMC/Paper.git
synced 2024-10-30 07:19:58 +01:00
afe633df08
* convert API tests to mockito * convert server tests to mockito * add co-author
78 lines
5.2 KiB
Diff
78 lines
5.2 KiB
Diff
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 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 bb7dd7a81a2af3d2a7df9d117f0d6395ecaed61b..28ce257b54f224b801a5206dd6d39cbae0ef248b 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
|
|
@@ -140,7 +140,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")) && SkullBlockEntity.profileCache != null && SkullBlockEntity.sessionService != null) {
|
|
SkullBlockEntity.profileCache.getAsync(owner.getName(), (optional) -> {
|
|
- Util.backgroundExecutor().execute(() -> {
|
|
+ Util.PROFILE_EXECUTOR.execute(() -> { // Paper - not a good idea to use BLOCKING OPERATIONS on the worldgen executor
|
|
Util.ifElse(optional, (gameprofile1) -> {
|
|
Property property = (Property) Iterables.getFirst(gameprofile1.getProperties().get("textures"), (Object) 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<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() {
|