aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0687-Execute-chunk-tasks-mid-tick.patch
diff options
context:
space:
mode:
authorbooky10 <[email protected]>2023-11-04 20:20:01 +0100
committerGitHub <[email protected]>2023-11-04 20:20:01 +0100
commitf78d7ce8ffb7e4b6fd5ee256f5e3678ea04fd807 (patch)
tree8e7abee5129e15a919630824c4f194a2811f7242 /patches/server/0687-Execute-chunk-tasks-mid-tick.patch
parent44057da46727138e19d951b56e98ad8c25c1f869 (diff)
downloadPaper-f78d7ce8ffb7e4b6fd5ee256f5e3678ea04fd807.tar.gz
Paper-f78d7ce8ffb7e4b6fd5ee256f5e3678ea04fd807.zip
Remove "fix-curing-zombie-villager-discount" exploit option (#9895)
Diffstat (limited to 'patches/server/0687-Execute-chunk-tasks-mid-tick.patch')
-rw-r--r--patches/server/0687-Execute-chunk-tasks-mid-tick.patch179
1 files changed, 179 insertions, 0 deletions
diff --git a/patches/server/0687-Execute-chunk-tasks-mid-tick.patch b/patches/server/0687-Execute-chunk-tasks-mid-tick.patch
new file mode 100644
index 0000000000..3a0637b6e5
--- /dev/null
+++ b/patches/server/0687-Execute-chunk-tasks-mid-tick.patch
@@ -0,0 +1,179 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Spottedleaf <[email protected]>
+Date: Mon, 6 Apr 2020 04:20:44 -0700
+Subject: [PATCH] Execute chunk tasks mid-tick
+
+This will help the server load chunks if tick times are high.
+
+diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java
+index 678a31fb85947ee8807d02d0fe4e11a73d2dafaa..0fc4feb00940079c4eb9554a3a48d19cbbeeb7bc 100644
+--- a/src/main/java/co/aikar/timings/MinecraftTimings.java
++++ b/src/main/java/co/aikar/timings/MinecraftTimings.java
+@@ -49,6 +49,8 @@ public final class MinecraftTimings {
+ public static final Timing scoreboardScoreSearch = Timings.ofSafe("Scoreboard score search"); // Paper - add timings for scoreboard search
+
+
++ public static final Timing midTickChunkTasks = Timings.ofSafe("Mid Tick Chunk Tasks");
++
+ private static final Map<Class<?>, String> taskNameCache = new MapMaker().weakKeys().makeMap();
+
+ private MinecraftTimings() {}
+diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
+index d74313b58b660f3c03b8a6db4f80b6b073b6b795..f7c1d07c95f7b67e32bd6679af88612aec74f54f 100644
+--- a/src/main/java/net/minecraft/server/MinecraftServer.java
++++ b/src/main/java/net/minecraft/server/MinecraftServer.java
+@@ -1285,6 +1285,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+
+ private boolean pollTaskInternal() {
+ if (super.pollTask()) {
++ this.executeMidTickTasks(); // Paper - execute chunk tasks mid tick
+ return true;
+ } else {
+ if (this.haveTime()) {
+@@ -2704,4 +2705,74 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+ }
+ }
+ // Paper end
++
++ // Paper start - execute chunk tasks mid tick
++ static final long CHUNK_TASK_QUEUE_BACKOFF_MIN_TIME = 25L * 1000L; // 25us
++ static final long MAX_CHUNK_EXEC_TIME = 1000L; // 1us
++
++ static final long TASK_EXECUTION_FAILURE_BACKOFF = 5L * 1000L; // 5us
++
++ private static long lastMidTickExecute;
++ private static long lastMidTickExecuteFailure;
++
++ private boolean tickMidTickTasks() {
++ // give all worlds a fair chance at by targetting them all.
++ // if we execute too many tasks, that's fine - we have logic to correctly handle overuse of allocated time.
++ boolean executed = false;
++ for (ServerLevel world : this.getAllLevels()) {
++ long currTime = System.nanoTime();
++ if (currTime - world.lastMidTickExecuteFailure <= TASK_EXECUTION_FAILURE_BACKOFF) {
++ continue;
++ }
++ if (!world.getChunkSource().pollTask()) {
++ // we need to back off if this fails
++ world.lastMidTickExecuteFailure = currTime;
++ } else {
++ executed = true;
++ }
++ }
++
++ return executed;
++ }
++
++ public final void executeMidTickTasks() {
++ org.spigotmc.AsyncCatcher.catchOp("mid tick chunk task execution");
++ long startTime = System.nanoTime();
++ if ((startTime - lastMidTickExecute) <= CHUNK_TASK_QUEUE_BACKOFF_MIN_TIME || (startTime - lastMidTickExecuteFailure) <= TASK_EXECUTION_FAILURE_BACKOFF) {
++ // it's shown to be bad to constantly hit the queue (chunk loads slow to a crawl), even if no tasks are executed.
++ // so, backoff to prevent this
++ return;
++ }
++
++ co.aikar.timings.MinecraftTimings.midTickChunkTasks.startTiming();
++ try {
++ for (;;) {
++ boolean moreTasks = this.tickMidTickTasks();
++ long currTime = System.nanoTime();
++ long diff = currTime - startTime;
++
++ if (!moreTasks || diff >= MAX_CHUNK_EXEC_TIME) {
++ if (!moreTasks) {
++ lastMidTickExecuteFailure = currTime;
++ }
++
++ // note: negative values reduce the time
++ long overuse = diff - MAX_CHUNK_EXEC_TIME;
++ if (overuse >= (10L * 1000L * 1000L)) { // 10ms
++ // make sure something like a GC or dumb plugin doesn't screw us over...
++ overuse = 10L * 1000L * 1000L; // 10ms
++ }
++
++ double overuseCount = (double)overuse/(double)MAX_CHUNK_EXEC_TIME;
++ long extraSleep = (long)Math.round(overuseCount*CHUNK_TASK_QUEUE_BACKOFF_MIN_TIME);
++
++ lastMidTickExecute = currTime + extraSleep;
++ return;
++ }
++ }
++ } finally {
++ co.aikar.timings.MinecraftTimings.midTickChunkTasks.stopTiming();
++ }
++ }
++ // Paper end - execute chunk tasks mid tick
+ }
+diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+index 4e58f31e4852a0811f85596653f6db630a75b069..8907396dc21dbfb31ff15286a7daa2110f6e34c0 100644
+--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+@@ -571,6 +571,7 @@ public class ServerChunkCache extends ChunkSource {
+ // Paper end
+ Iterator iterator1 = list.iterator();
+
++ int chunksTicked = 0; // Paper
+ while (iterator1.hasNext()) {
+ ServerChunkCache.ChunkAndHolder chunkproviderserver_a = (ServerChunkCache.ChunkAndHolder) iterator1.next();
+ LevelChunk chunk1 = chunkproviderserver_a.chunk;
+@@ -584,6 +585,7 @@ public class ServerChunkCache extends ChunkSource {
+
+ if (this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) {
+ this.level.tickChunk(chunk1, k);
++ if ((chunksTicked++ & 1) == 0) net.minecraft.server.MinecraftServer.getServer().executeMidTickTasks(); // Paper
+ }
+ }
+ }
+diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
+index 48513493d92ea0fe5e2cb4f021c843b10caab062..82867a6d6e2277355269712e9e45602fc7afac45 100644
+--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
+@@ -215,6 +215,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+ private final StructureCheck structureCheck;
+ private final boolean tickTime;
+ private final RandomSequences randomSequences;
++ public long lastMidTickExecuteFailure; // Paper - execute chunk tasks mid tick
+
+ // CraftBukkit start
+ public final LevelStorageSource.LevelStorageAccess convertable;
+@@ -1187,6 +1188,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+ if (fluid1.is(fluid)) {
+ fluid1.tick(this, pos);
+ }
++ MinecraftServer.getServer().executeMidTickTasks(); // Paper - exec chunk tasks during world tick
+
+ }
+
+@@ -1196,6 +1198,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
+ if (iblockdata.is(block)) {
+ iblockdata.tick(this, pos, this.random);
+ }
++ MinecraftServer.getServer().executeMidTickTasks(); // Paper - exec chunk tasks during world tick
+
+ }
+
+diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
+index 6bd9b680fa1e84d058ada2354fa6a5b876185dc4..795be71432c4d834004bcfb70a8d1927cf22bfda 100644
+--- a/src/main/java/net/minecraft/world/level/Level.java
++++ b/src/main/java/net/minecraft/world/level/Level.java
+@@ -918,6 +918,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+ // Spigot end
+ } else if (this.shouldTickBlocksAt(tickingblockentity.getPos())) {
+ tickingblockentity.tick();
++ // Paper start - execute chunk tasks during tick
++ if ((this.tileTickPosition & 7) == 0) {
++ MinecraftServer.getServer().executeMidTickTasks();
++ }
++ // Paper end - execute chunk tasks during tick
+ }
+ }
+ this.blockEntityTickers.removeAll(toRemove);
+@@ -932,6 +937,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
+ public <T extends Entity> void guardEntityTick(Consumer<T> tickConsumer, T entity) {
+ try {
+ tickConsumer.accept(entity);
++ MinecraftServer.getServer().executeMidTickTasks(); // Paper - execute chunk tasks mid tick
+ } catch (Throwable throwable) {
+ if (throwable instanceof ThreadDeath) throw throwable; // Paper
+ // Paper start - Prevent tile entity and entity crashes