From d22c87128e573d67a40bdad8ab39973cb794a8e3 Mon Sep 17 00:00:00 2001 From: violetc <58360096+s-yh-china@users.noreply.github.com> Date: Fri, 25 Nov 2022 16:51:51 +0800 Subject: [PATCH] Remove busy wait in async execution utility --- patches/server/0002-Leaves-Server-Utils.patch | 62 +++++++++++++------ .../server/0019-Optimize-mob-spawning.patch | 10 +-- 2 files changed, 48 insertions(+), 24 deletions(-) diff --git a/patches/server/0002-Leaves-Server-Utils.patch b/patches/server/0002-Leaves-Server-Utils.patch index 5b4c138c..44ac79cf 100644 --- a/patches/server/0002-Leaves-Server-Utils.patch +++ b/patches/server/0002-Leaves-Server-Utils.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Leaves Server Utils diff --git a/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java -index c89f6986eda5a132a948732ea1b6923370685317..5a0655dabc032a29062dfdd9f9d3fc9e8d25f6b7 100644 +index 41b9405d6759d865e0d14dd4f95163e9690e967d..67008112e1d1c059938838c544f093fa1f0a4fee 100644 --- a/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java +++ b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java @@ -26,7 +26,7 @@ public abstract class AreaMap { @@ -54,31 +54,32 @@ index 0000000000000000000000000000000000000000..890b91a95719f18a75bc2c2176ef5cb9 +} diff --git a/src/main/java/top/leavesmc/leaves/util/AsyncExecutor.java b/src/main/java/top/leavesmc/leaves/util/AsyncExecutor.java new file mode 100644 -index 0000000000000000000000000000000000000000..1c5449426b69dc711ca935f57cd8180f56219879 +index 0000000000000000000000000000000000000000..0c03f3f051eff7abaacfaa8adb992811f934b9c8 --- /dev/null +++ b/src/main/java/top/leavesmc/leaves/util/AsyncExecutor.java -@@ -0,0 +1,52 @@ +@@ -0,0 +1,76 @@ +package top.leavesmc.leaves.util; + +import com.google.common.collect.Queues; +import top.leavesmc.leaves.LeavesLogger; + +import java.util.Queue; -+import java.util.concurrent.locks.LockSupport; -+import java.util.function.BooleanSupplier; ++import java.util.concurrent.locks.Condition; ++import java.util.concurrent.locks.Lock; ++import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Level; + +// Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) +public class AsyncExecutor implements Runnable { + -+ private Queue jobs = Queues.newConcurrentLinkedQueue(); ++ private final Queue jobs = Queues.newArrayDeque(); ++ private final Lock mutex = new ReentrantLock(); ++ private final Condition cond = mutex.newCondition(); + private final Thread thread; -+ private final BooleanSupplier shouldRun; + private volatile boolean killswitch = false; + -+ public AsyncExecutor(String threadName, BooleanSupplier shouldRun) { ++ public AsyncExecutor(String threadName) { + this.thread = new Thread(this, threadName); -+ this.shouldRun = shouldRun; + } + + public void start() { @@ -87,26 +88,49 @@ index 0000000000000000000000000000000000000000..1c5449426b69dc711ca935f57cd8180f + + public void kill() { + killswitch = true; ++ cond.signalAll(); + } + + public void submit(Runnable runnable) { -+ jobs.offer(runnable); ++ mutex.lock(); ++ try { ++ jobs.offer(runnable); ++ cond.signalAll(); ++ } finally { ++ mutex.unlock(); ++ } + } + + @Override + public void run() { + while (!killswitch) { -+ if (shouldRun.getAsBoolean()) { -+ try { -+ Runnable runnable; -+ while ((runnable = jobs.poll()) != null) { -+ runnable.run(); -+ } -+ } catch (Exception e) { -+ LeavesLogger.LOGGER.log(Level.SEVERE, e, () -> "Failed to execute async job for thread " + thread.getName()); ++ try { ++ Runnable runnable = takeRunnable(); ++ if (runnable != null) { ++ runnable.run(); + } ++ } catch (InterruptedException e) { ++ Thread.currentThread().interrupt(); ++ } catch (Exception e) { ++ LeavesLogger.LOGGER.log(Level.SEVERE, e, () -> "Failed to execute async job for thread " + thread.getName()); + } -+ LockSupport.parkNanos("executing tasks", 1000L); ++ } ++ } ++ ++ private Runnable takeRunnable() throws InterruptedException { ++ mutex.lock(); ++ try { ++ while (jobs.isEmpty() && !killswitch) { ++ cond.await(); ++ } ++ ++ if (jobs.isEmpty()) { ++ return null; ++ } ++ ++ return jobs.remove(); ++ } finally { ++ mutex.unlock(); + } + } +} diff --git a/patches/server/0019-Optimize-mob-spawning.patch b/patches/server/0019-Optimize-mob-spawning.patch index fb6c0b7b..52586d20 100644 --- a/patches/server/0019-Optimize-mob-spawning.patch +++ b/patches/server/0019-Optimize-mob-spawning.patch @@ -6,20 +6,20 @@ Subject: [PATCH] Optimize mob spawning This patch is Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 3775a75a54807e50eded612f26fec5ad0229fbca..905103d883311296a914e10a31e13ba9353352f8 100644 +index 595d2bf02a30d91535f8bc509aa8c37a840c274a..c4984f0d27e66e201b126a0f3649f6534b0cef53 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -301,6 +301,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop true); // Leaves - optimize mob spawning ++ public top.leavesmc.leaves.util.AsyncExecutor mobSpawnExecutor = new top.leavesmc.leaves.util.AsyncExecutor("MobSpawning"); // Leaves - optimize mob spawning + public static S spin(Function serverFactory) { AtomicReference atomicreference = new AtomicReference(); Thread thread = new io.papermc.paper.util.TickThread(() -> { // Paper - rewrite chunk system diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index bfcaadc4bd70384d5cea975b18874cfc31d8909e..aa112d6e0e3a91ef9cf74a0fe9d105416f9a161d 100644 +index 03989bb74e56c743fbb115518971061ad72355d3..12dd19556a13990f3ed0b50384e8352b5d944822 100644 --- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java +++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java @@ -341,6 +341,11 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface @@ -35,7 +35,7 @@ index bfcaadc4bd70384d5cea975b18874cfc31d8909e..aa112d6e0e3a91ef9cf74a0fe9d10541 } } diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 73daa8368066e20d251b8b6eb69c916919b48838..9e40e93e233d1f5865681f749cb19454b5f4b65e 100644 +index 55d8ced734a408c990c6c4fbc81707bcb1f27daa..132bb7595af5106edd84ff2a6efa823aceee35bc 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -334,7 +334,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider @@ -48,7 +48,7 @@ index 73daa8368066e20d251b8b6eb69c916919b48838..9e40e93e233d1f5865681f749cb19454 this.playerEntityTrackerTrackMaps = new com.destroystokyo.paper.util.misc.PlayerAreaMap[TRACKING_RANGE_TYPES.length]; this.entityTrackerTrackRanges = new int[TRACKING_RANGE_TYPES.length]; diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 6d1f929eb717f62f0d7ebb9e9b52c3788061e240..7d7501e85874e60263d5462dba02a4b3a79f68cb 100644 +index 4ff563d903633f181e1268daa77f250cfec204a0..b9c1d62b13465db6d435d1cda72ca759d8f0d22d 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java @@ -76,6 +76,11 @@ public class ServerChunkCache extends ChunkSource {