From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Spottedleaf 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 7a4234abf620b8394307fa01913bc00215a64e23..4b467f1af93452d13829f756d55dee18b8889d40 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 distanceManagerTick = Timings.ofSafe("Distance Manager Tick"); // Paper - add timings for distance manager + public static final Timing midTickChunkTasks = Timings.ofSafe("Mid Tick Chunk Tasks"); + private static final Map, 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 e2e37b75475c7c243245ca3ff78d29c51ff0ad39..399cb6d50b5a49ab873fab9b5f86c986364d49c3 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1353,8 +1353,79 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop= 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 + private boolean pollTaskInternal() { if (super.pollTask()) { + this.executeMidTickTasks(); // Paper - execute chunk tasks mid tick return true; } else { boolean ret = false; // Paper - force execution of all worlds, do not just bias the first diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java index 3b0fd733e8fd9639362f251876bea814a2515618..c2973fcfde402b5432db37468e4a40a1a119cca1 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java +++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java @@ -583,6 +583,7 @@ public class ServerChunkCache extends ChunkSource { boolean flag1 = this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) != 0L && this.level.getLevelData().getGameTime() % this.level.ticksPerSpawnCategory.getLong(org.bukkit.entity.SpawnCategory.ANIMAL) == 0L; // CraftBukkit Iterator iterator1 = list.iterator(); + int chunksTicked = 0; // Paper while (iterator1.hasNext()) { ServerChunkCache.ChunkAndHolder chunkproviderserver_a = (ServerChunkCache.ChunkAndHolder) iterator1.next(); LevelChunk chunk1 = chunkproviderserver_a.chunk; @@ -596,6 +597,7 @@ public class ServerChunkCache extends ChunkSource { if (this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { this.level.tickChunk(chunk1, l); + 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 715f6fb68d832545f36184a77f2229c2a1a79f75..ac5c505a9d280fb128bbc59526bb8bbe7aaaf307 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -216,6 +216,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; @@ -1205,6 +1206,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 } @@ -1214,6 +1216,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 f4f2f423b5c9a6bf5cc9aee008b740385beb4045..6b47b8fe38080a2b99bbdc8596f2b607ff0ff4c9 100644 --- a/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java @@ -929,6 +929,11 @@ public abstract class Level implements LevelAccessor, AutoCloseable { // Spigot end } else if (flag && 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); // Paper - Fix MC-117075 @@ -943,6 +948,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public void guardEntityTick(Consumer 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