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/com/destroystokyo/paper/server/ticklist/PaperTickList.java b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java index 4666d6582535d6e49c5bd40d4fcdcdfe07590aa9..b870cca05f0ba354e6976a70511235636093d13c 100644 --- a/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java +++ b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java @@ -310,6 +310,7 @@ public final class PaperTickList extends TickListServer { // extend to avo if (toTick.tickState == STATE_TICKING) { toTick.tickState = STATE_TICKED; } // else it's STATE_CANCELLED_TICK + MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - exec chunk tasks during world tick } else { // re-schedule eventually toTick.tickState = STATE_SCHEDULED; diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java index 419d17d0eb9426e4f3f9f97a504e567401d175f3..dae8824a6034cdaaecbedeba5e05c62f4565583f 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1115,7 +1115,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant= 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(); + } + } + // Tuinity end - execute chunk tasks mid tick + private void executeModerately() { this.executeAll(); java.util.concurrent.locks.LockSupport.parkNanos("executing tasks", 1000L); @@ -1221,22 +1291,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant { - midTickLoadChunks(); // will only do loads since we are still considered !canSleepForTick + // Tuinity - replace logic return !this.canOversleep(); }); isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); @@ -1421,16 +1477,16 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant list = Lists.newArrayList(this.playerChunkMap.f()); // Paper @@ -1029,7 +1031,7 @@ public class ChunkProviderServer extends IChunkProvider { this.world.timings.chunkTicks.startTiming(); // Spigot // Paper this.world.a(chunk, k); this.world.timings.chunkTicks.stopTiming(); // Spigot // Paper - if (chunksTicked[0]++ % 10 == 0) this.world.getMinecraftServer().midTickLoadChunks(); // Paper + if ((++ticked & 1) == 0) MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - exec chunk tasks during world tick } } } @@ -1185,41 +1187,7 @@ public class ChunkProviderServer extends IChunkProvider { ChunkProviderServer.this.world.getMethodProfiler().c("runTask"); super.executeTask(runnable); } - - // Paper start - private long lastMidTickChunkTask = 0; - public boolean pollChunkLoadTasks() { - if (com.destroystokyo.paper.io.chunk.ChunkTaskManager.pollChunkWaitQueue() || ChunkProviderServer.this.world.asyncChunkTaskManager.pollNextChunkTask()) { - try { - ChunkProviderServer.this.tickDistanceManager(); - } finally { - // from below: process pending Chunk loadCallback() and unloadCallback() after each run task - playerChunkMap.callbackExecutor.run(); - } - return true; - } - return false; - } - public void midTickLoadChunks() { - MinecraftServer server = ChunkProviderServer.this.world.getMinecraftServer(); - // always try to load chunks, restrain generation/other updates only. don't count these towards tick count - //noinspection StatementWithEmptyBody - while (pollChunkLoadTasks()) {} - - if (System.nanoTime() - lastMidTickChunkTask < 200000) { - return; - } - - for (;server.midTickChunksTasksRan < com.destroystokyo.paper.PaperConfig.midTickChunkTasks && server.canSleepForTick();) { - if (this.executeNext()) { - server.midTickChunksTasksRan++; - lastMidTickChunkTask = System.nanoTime(); - } else { - break; - } - } - } - // Paper end + // Tuinity - replace logic @Override protected boolean executeNext() { diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java index 25073eb392bb00daf7e0b68be4767cea416c1816..1658c03b70b5984c87d069276efcc7b8c8878431 100644 --- a/src/main/java/net/minecraft/server/level/WorldServer.java +++ b/src/main/java/net/minecraft/server/level/WorldServer.java @@ -410,6 +410,10 @@ public class WorldServer extends World implements GeneratorAccessSeed { } // Tuinity end + // Tuinity start - execute chunk tasks mid tick + public long lastMidTickExecuteFailure; + // Tuinity end - execute chunk tasks mid tick + // Add env and gen to constructor, WorldData -> WorldDataServer public WorldServer(MinecraftServer minecraftserver, Executor executor, Convertable.ConversionSession convertable_conversionsession, IWorldDataServer iworlddataserver, ResourceKey resourcekey, DimensionManager dimensionmanager, WorldLoadListener worldloadlistener, ChunkGenerator chunkgenerator, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen) { super(iworlddataserver, resourcekey, dimensionmanager, minecraftserver::getMethodProfiler, false, flag, i, gen, env, executor); // Paper pass executor @@ -674,7 +678,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { } timings.scheduledBlocks.stopTiming(); // Paper - this.getMinecraftServer().midTickLoadChunks(); // Paper + // Tuinity - replace logic gameprofilerfiller.exitEnter("raid"); this.timings.raids.startTiming(); // Paper - timings this.persistentRaid.a(); @@ -683,7 +687,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { timings.doSounds.startTiming(); // Spigot this.ak(); timings.doSounds.stopTiming(); // Spigot - this.getMinecraftServer().midTickLoadChunks(); // Paper + // Tuinity - replace logic this.ticking = false; gameprofilerfiller.exitEnter("entities"); boolean flag3 = true || !this.players.isEmpty() || !this.getForceLoadedChunks().isEmpty(); // CraftBukkit - this prevents entity cleanup, other issues on servers with no players @@ -760,7 +764,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { } this.afterEntityTickingTasks.clear(); // Paper end - this.getMinecraftServer().midTickLoadChunks(); // Paper + // Tuinity - replace logic Entity entity2; @@ -770,7 +774,7 @@ public class WorldServer extends World implements GeneratorAccessSeed { } timings.tickEntities.stopTiming(); // Spigot - this.getMinecraftServer().midTickLoadChunks(); // Paper + // Tuinity - replace logic this.tickBlockEntities(); } diff --git a/src/main/java/net/minecraft/world/level/World.java b/src/main/java/net/minecraft/world/level/World.java index 74894282575d12f25ba4968abf873d3a346529b7..89d43183cf6c628c124aba486db69336f1e017df 100644 --- a/src/main/java/net/minecraft/world/level/World.java +++ b/src/main/java/net/minecraft/world/level/World.java @@ -960,6 +960,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { return; // Paper end } + MinecraftServer.getServer().executeMidTickTasks(); // Tuinity - execute chunk tasks mid tick } // Paper start - Prevent armor stands from doing entity lookups @Override