From d79bdd54f5b6d876d608556117755f7d4264aab9 Mon Sep 17 00:00:00 2001 From: Martijn Muijsers Date: Tue, 31 Jan 2023 22:45:28 +0100 Subject: [PATCH] Define server children tick steps --- patches/server/0157-Split-tick-steps.patch | 118 +++++------ ...58-Define-server-children-tick-steps.patch | 199 ++++++++++++++++++ 2 files changed, 253 insertions(+), 64 deletions(-) create mode 100644 patches/server/0158-Define-server-children-tick-steps.patch diff --git a/patches/server/0157-Split-tick-steps.patch b/patches/server/0157-Split-tick-steps.patch index 78defde..bc49e8c 100644 --- a/patches/server/0157-Split-tick-steps.patch +++ b/patches/server/0157-Split-tick-steps.patch @@ -7,7 +7,7 @@ License: AGPL-3.0 (https://www.gnu.org/licenses/agpl-3.0.html) Gale - https://galemc.org diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 7ed820d2483bf6741a355b062f062a04866ba938..cf270ad8f63ab6351be654525d195d802a41e55c 100644 +index 7ed820d2483bf6741a355b062f062a04866ba938..d39b432ed49257901e0432c73ecd1a84f404a8d2 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -42,6 +42,7 @@ import java.util.concurrent.CompletableFuture; @@ -38,45 +38,45 @@ index 7ed820d2483bf6741a355b062f062a04866ba938..cf270ad8f63ab6351be654525d195d80 public void tickChildren(BooleanSupplier shouldKeepTicking) { + // Gale start - split tick steps + tick_shouldKeepTicking = shouldKeepTicking; -+ this.tickStep_doSchedulerHeartbeat.run(); -+ this.tickStep_tickFunctions.run(); ++ this.tickStep_doSchedulerHeartbeat(); ++ this.tickStep_tickFunctions(); + //Iterator iterator = this.getAllLevels().iterator(); // Paper - moved down -+ this.tickStep_runProcessQueueTasks.run(); ++ this.tickStep_runProcessQueueTasks(); + for (final ServerLevel world : this.getAllLevelsArray()) { // Gale - base thread pool - optimize server levels -+ this.tickStep_sendTimeUpdates.accept(world); ++ this.tickStep_sendTimeUpdates(world); + } -+ this.tickStep_startIteratingOverLevels.run(); ++ this.tickStep_startIteratingOverLevels(); + for (ServerLevel worldserver : this.getAllLevelsArray()) { // Paper - move down // Gale - base thread pool - optimize server levels -+ this.tickStep_updateEvents.accept(worldserver); -+ this.tickStep_tickWorld.accept(worldserver); -+ this.tickStep_recalculateRegions.accept(worldserver); -+ this.tickStep_clearExplosionDensity.accept(worldserver); ++ this.tickStep_updateEvents(worldserver); ++ this.tickStep_tickWorld(worldserver); ++ this.tickStep_recalculateRegions(worldserver); ++ this.tickStep_clearExplosionDensity(worldserver); + } -+ this.tickStep_stopIteratingOverLevels.run(); -+ this.tickStep_tickConnection.run(); -+ this.tickStep_tickPlayerList.run(); -+ this.tickStep_tickGameTestTicker.run(); -+ this.tickStep_runTickables.run(); ++ this.tickStep_stopIteratingOverLevels(); ++ this.tickStep_tickConnection(); ++ this.tickStep_tickPlayerList(); ++ this.tickStep_tickGameTestTicker(); ++ this.tickStep_runTickables(); + } + -+ public final Runnable tickStep_doSchedulerHeartbeat = () -> { ++ public final void tickStep_doSchedulerHeartbeat() { + // Gale end - split tick steps MinecraftTimings.bukkitSchedulerTimer.startTiming(); // Spigot // Paper this.server.getScheduler().mainThreadHeartbeat(this.tickCount); // CraftBukkit MinecraftTimings.bukkitSchedulerTimer.stopTiming(); // Spigot // Paper + // Gale start - split tick steps -+ }; ++ } + -+ public final Runnable tickStep_tickFunctions = () -> { ++ public final void tickStep_tickFunctions() { + // Gale end - split tick steps MinecraftTimings.commandFunctionsTimer.startTiming(); // Spigot // Paper this.getFunctions().tick(); MinecraftTimings.commandFunctionsTimer.stopTiming(); // Spigot // Paper - //Iterator iterator = this.getAllLevels().iterator(); // Paper - moved down + // Gale start - split tick steps -+ }; ++ } -+ public final Runnable tickStep_runProcessQueueTasks = () -> { ++ public final void tickStep_runProcessQueueTasks() { + // Gale end - split tick steps // CraftBukkit start // Run tasks that are waiting on processing @@ -86,9 +86,9 @@ index 7ed820d2483bf6741a355b062f062a04866ba938..cf270ad8f63ab6351be654525d195d80 } MinecraftTimings.processQueueTimer.stopTiming(); // Spigot + // Gale start - split tick steps -+ }; ++ } -+ public final Consumer tickStep_sendTimeUpdates = world -> { ++ public final void tickStep_sendTimeUpdates(ServerLevel world) { + // Gale end - split tick steps MinecraftTimings.timeUpdateTimer.startTiming(); // Spigot // Paper // Send time updates to everyone, it will get the right time from the world the player is in. @@ -105,46 +105,39 @@ index 7ed820d2483bf6741a355b062f062a04866ba938..cf270ad8f63ab6351be654525d195d80 // Paper end MinecraftTimings.timeUpdateTimer.stopTiming(); // Spigot // Paper + // Gale start - split tick steps -+ }; ++ } -+ public final Runnable tickStep_startIteratingOverLevels = () -> { ++ public final void tickStep_startIteratingOverLevels() { + // Gale end - split tick steps this.isIteratingOverLevels = true; // Paper - for (ServerLevel worldserver : this.getAllLevelsArray()) { // Paper - move down // Gale - base thread pool - optimize server levels + // Gale start - split tick steps -+ }; ++ } + -+ public final Consumer tickStep_updateEvents = worldserver -> { ++ public final void tickStep_updateEvents(ServerLevel worldserver) { + // Gale end - split tick steps worldserver.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper worldserver.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = worldserver.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper -+ }; // Gale - split tick steps ++ } // Gale - split tick steps /* Drop global time updates if (this.tickCount % 20 == 0) { -@@ -1629,16 +1678,33 @@ public abstract class MinecraftServer extends MinecraftServerBlockableEventLoop +@@ -1629,16 +1678,28 @@ public abstract class MinecraftServer extends MinecraftServerBlockableEventLoop } // CraftBukkit end */ -+ public static Consumer wrapThrowingWorldTickStep(Consumer consumer) { -+ return worldserver -> { - try { -+ consumer.accept(worldserver); -+ } catch (Throwable throwable) { -+ SERVER.catchWorldTickException(worldserver, throwable); -+ } -+ }; +- try { +- worldserver.timings.doTick.startTiming(); // Spigot +- worldserver.tick(shouldKeepTicking); ++ public final void tickStep_tickWorld(ServerLevel worldserver) { ++ worldserver.tick(tick_shouldKeepTicking); + } + -+ public final Consumer tickStep_tickWorld = worldserver -> { -+ worldserver.tick(tick_shouldKeepTicking); -+ }; -+ -+ public final Consumer tickStep_recalculateRegions = wrapThrowingWorldTickStep(worldserver -> { - worldserver.timings.doTick.startTiming(); // Spigot -- worldserver.tick(shouldKeepTicking); -+ // Gale end - split tick steps ++ public final void tickStep_recalculateRegions(ServerLevel worldserver) { ++ try { ++ worldserver.timings.doTick.startTiming(); // Spigot ++ // Gale end - split tick steps // Paper start for (final io.papermc.paper.chunk.SingleThreadChunkRegionManager regionManager : worldserver.getChunkSource().chunkMap.regionManagers) { regionManager.recalculateRegions(); @@ -153,14 +146,18 @@ index 7ed820d2483bf6741a355b062f062a04866ba938..cf270ad8f63ab6351be654525d195d80 worldserver.timings.doTick.stopTiming(); // Spigot - } catch (Throwable throwable) { + // Paper end -+ }); ++ // Gale start - split tick steps ++ } catch (Throwable throwable) { ++ SERVER.catchWorldTickException(worldserver, throwable); ++ } ++ } + + public final void catchWorldTickException(ServerLevel worldserver, Throwable throwable) { + // Gale end - split tick steps // Spigot Start CrashReport crashreport; try { -@@ -1651,28 +1717,53 @@ public abstract class MinecraftServer extends MinecraftServerBlockableEventLoop +@@ -1651,22 +1712,47 @@ public abstract class MinecraftServer extends MinecraftServerBlockableEventLoop worldserver.fillReportDetails(crashreport); throw new ReportedException(crashreport); @@ -168,55 +165,48 @@ index 7ed820d2483bf6741a355b062f062a04866ba938..cf270ad8f63ab6351be654525d195d80 + // Gale start - split tick steps + } -+ public final Consumer tickStep_clearExplosionDensity = worldserver -> { ++ public final void tickStep_clearExplosionDensity(ServerLevel worldserver) { + // Gale end - split tick steps worldserver.explosionDensityCache.clear(); // Paper - Optimize explosions - } + // Gale start - split tick steps -+ }; ++ } + -+ public final Runnable tickStep_stopIteratingOverLevels = () -> { ++ public final void tickStep_stopIteratingOverLevels() { + // Gale end - split tick steps this.isIteratingOverLevels = false; // Paper + // Gale start - split tick steps -+ }; ++ } -+ public final Runnable tickStep_tickConnection = () -> { ++ public final void tickStep_tickConnection() { + // Gale end - split tick steps MinecraftTimings.connectionTimer.startTiming(); // Spigot this.getConnection().tick(); MinecraftTimings.connectionTimer.stopTiming(); // Spigot + // Gale start - split tick steps -+ }; ++ } + -+ public final Runnable tickStep_tickPlayerList = () -> { ++ public final void tickStep_tickPlayerList() { + // Gale end - split tick steps MinecraftTimings.playerListTimer.startTiming(); // Spigot // Paper this.playerList.tick(); MinecraftTimings.playerListTimer.stopTiming(); // Spigot // Paper + // Gale start - split tick steps -+ }; ++ } + -+ public final Runnable tickStep_tickGameTestTicker = () -> { ++ public final void tickStep_tickGameTestTicker() { + // Gale end - split tick steps if (SharedConstants.IS_RUNNING_IN_IDE) { GameTestTicker.SINGLETON.tick(); } + // Gale start - split tick steps -+ }; ++ } -+ public final Runnable tickStep_runTickables = () -> { ++ public final void tickStep_runTickables() { + // Gale end - split tick steps MinecraftTimings.tickablesTimer.startTiming(); // Spigot // Paper for (int i = 0; i < this.tickables.size(); ++i) { ((Runnable) this.tickables.get(i)).run(); - } - MinecraftTimings.tickablesTimer.stopTiming(); // Spigot // Paper -- } -+ }; - - public boolean isNetherEnabled() { - return true; diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java index ba352013692b987518dd200d376fb6cf2c90da19..99fe51c3654bf5f978b6576290504c7b7bf2e7a1 100644 --- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java diff --git a/patches/server/0158-Define-server-children-tick-steps.patch b/patches/server/0158-Define-server-children-tick-steps.patch new file mode 100644 index 0000000..2a47cef --- /dev/null +++ b/patches/server/0158-Define-server-children-tick-steps.patch @@ -0,0 +1,199 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martijn Muijsers +Date: Tue, 31 Jan 2023 22:39:10 +0100 +Subject: [PATCH] Define server children tick steps + +License: AGPL-3.0 (https://www.gnu.org/licenses/agpl-3.0.html) +Gale - https://galemc.org + +diff --git a/src/main/java/org/galemc/gale/tick/step/ServerChildrenTickSteps.java b/src/main/java/org/galemc/gale/tick/step/ServerChildrenTickSteps.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0e438fd13ef36bb7fd572286768ca231a2ef5039 +--- /dev/null ++++ b/src/main/java/org/galemc/gale/tick/step/ServerChildrenTickSteps.java +@@ -0,0 +1,107 @@ ++// Gale - multithreaded ticking ++ ++package org.galemc.gale.tick.step; ++ ++import net.minecraft.server.MinecraftServer; ++ ++/** ++ * A utility class defining the tick steps in {@link MinecraftServer#tickChildren} in a way ++ * that they can be executed both in the default order, or submitted as tasks that may run in parallel. ++ * ++ * @author Martijn Muijsers under AGPL-3.0 ++ */ ++public final class ServerChildrenTickSteps { ++ ++ private ServerChildrenTickSteps() {} ++ ++ public static final ServerTickStep doSchedulerHeartbeat = new ServerTickStep(() -> MinecraftServer.SERVER.tickStep_doSchedulerHeartbeat()); ++ public static final ServerTickStep tickFunctions = new ServerTickStep(() -> MinecraftServer.SERVER.tickStep_tickFunctions()); ++ public static final ServerTickStep runProcessQueueTasks = new ServerTickStep(() -> MinecraftServer.SERVER.tickStep_runProcessQueueTasks()); ++ public static final WorldTickStep sendTimeUpdates = new WorldTickStep(world -> MinecraftServer.SERVER.tickStep_sendTimeUpdates(world)); ++ public static final ServerTickStep startIteratingOverLevels = new ServerTickStep(() -> MinecraftServer.SERVER.tickStep_startIteratingOverLevels()); ++ public static final WorldTickStep updateEvents = new WorldTickStep(world -> MinecraftServer.SERVER.tickStep_updateEvents(world)); ++ ++ public static final WorldTickStep updatePlayersAffectingSpawning = new WorldTickStep(world -> world.tickStep_updatePlayersAffectingSpawning.run()); ++ public static final WorldTickStep startHandlingTick = new WorldTickStep(world -> world.tickStep_startHandlingTick.run()); ++ public static final WorldTickStep tickWorldBorder = new WorldTickStep(world -> world.tickStep_tickWorldBorder.run()); ++ public static final WorldTickStep advanceWeatherCycle = new WorldTickStep(world -> world.tickStep_advanceWeatherCycle.run()); ++ public static final WorldTickStep applySleep = new WorldTickStep(world -> world.tickStep_applySleep.run()); ++ public static final WorldTickStep updateSkyBrightness = new WorldTickStep(world -> world.tickStep_updateSkyBrightness.run()); ++ public static final WorldTickStep tickTime = new WorldTickStep(world -> world.tickStep_tickTime.run()); ++ public static final WorldTickStep setScheduledBlocksGameTime = new WorldTickStep(world -> world.tickStep_setScheduledBlocksGameTime.run()); ++ public static final WorldTickStep setIsDebug = new WorldTickStep(world -> world.tickStep_setIsDebug.run()); ++ public static final WorldTickStep tickBlocks = new WorldTickStep(world -> world.tickStep_tickBlocks.run()); ++ public static final WorldTickStep tickFluids = new WorldTickStep(world -> world.tickStep_tickFluids.run()); ++ public static final WorldTickStep tickRaids = new WorldTickStep(world -> world.tickStep_tickRaids.run()); ++ ++ public static final WorldTickStep purgeStaleTickets = new WorldTickStep(world -> world.getChunkSource().tickStep_purgeStaleTickets.run()); ++ public static final WorldTickStep runDistanceManagerUpdates = new WorldTickStep(world -> world.getChunkSource().tickStep_runDistanceManagerUpdates.run()); ++ public static final WorldTickStep tickChunks = new WorldTickStep(world -> world.getChunkSource().tickStep_tickChunks.run()); ++ public static final WorldTickStep tickChunkMap = new WorldTickStep(world -> world.getChunkSource().tickStep_tickChunkMap.run()); ++ public static final WorldTickStep clearCache = new WorldTickStep(world -> world.getChunkSource().tickStep_clearCache.run()); ++ ++ public static final WorldTickStep doRunBlockEvents = new WorldTickStep(world -> world.tickStep_doRunBlockEvents.run()); ++ public static final WorldTickStep stopHandlingTick = new WorldTickStep(world -> world.tickStep_stopHandlingTick.run()); ++ public static final WorldTickStep setDoEntityAndBlockEntityTick = new WorldTickStep(world -> world.tickStep_setDoEntityAndBlockEntityTick.run()); ++ public static final WorldTickStep tickDragonFight = new WorldTickStep(world -> world.tickStep_tickDragonFight.run()); ++ public static final WorldTickStep activateEntities = new WorldTickStep(world -> world.tickStep_activateEntities.run()); ++ public static final WorldTickStep tickEntityList = new WorldTickStep(world -> world.tickStep_tickEntityList.run()); ++ public static final WorldTickStep tickBlockEntities = new WorldTickStep(world -> world.tickStep_tickBlockEntities.run()); ++ ++ public static final WorldTickStep recalculateRegions = new WorldTickStep(world -> MinecraftServer.SERVER.tickStep_recalculateRegions(world)); ++ public static final WorldTickStep clearExplosionDensity = new WorldTickStep(world -> MinecraftServer.SERVER.tickStep_clearExplosionDensity(world)); ++ public static final ServerTickStep stopIteratingOverLevels = new ServerTickStep(() -> MinecraftServer.SERVER.tickStep_stopIteratingOverLevels()); ++ public static final ServerTickStep tickConnection = new ServerTickStep(() -> MinecraftServer.SERVER.tickStep_tickConnection()); ++ public static final ServerTickStep tickPlayerList = new ServerTickStep(() -> MinecraftServer.SERVER.tickStep_tickPlayerList()); ++ public static final ServerTickStep tickGameTestTicker = new ServerTickStep(() -> MinecraftServer.SERVER.tickStep_tickGameTestTicker()); ++ public static final ServerTickStep runTickables = new ServerTickStep(() -> MinecraftServer.SERVER.tickStep_runTickables()); ++ ++ /** ++ * The {@linkplain TickStep tick steps} that occur in {@link MinecraftServer#tickChildren}, ++ * in the same order. ++ */ ++ public static final TickStep[] values = { ++ doSchedulerHeartbeat, ++ tickFunctions, ++ runProcessQueueTasks, ++ sendTimeUpdates, ++ startIteratingOverLevels, ++ updateEvents, ++ ++ updatePlayersAffectingSpawning, ++ startHandlingTick, ++ tickWorldBorder, ++ advanceWeatherCycle, ++ applySleep, ++ updateSkyBrightness, ++ tickTime, ++ setScheduledBlocksGameTime, ++ setIsDebug, ++ tickBlocks, ++ tickFluids, ++ tickRaids, ++ ++ purgeStaleTickets, ++ runDistanceManagerUpdates, ++ tickChunks, ++ tickChunkMap, ++ clearCache, ++ ++ doRunBlockEvents, ++ stopHandlingTick, ++ setDoEntityAndBlockEntityTick, ++ tickDragonFight, ++ activateEntities, ++ tickEntityList, ++ tickBlockEntities, ++ ++ recalculateRegions, ++ clearExplosionDensity, ++ stopIteratingOverLevels, ++ tickConnection, ++ tickPlayerList, ++ tickGameTestTicker, ++ runTickables ++ }; ++ ++} +diff --git a/src/main/java/org/galemc/gale/tick/step/ServerTickStep.java b/src/main/java/org/galemc/gale/tick/step/ServerTickStep.java +new file mode 100644 +index 0000000000000000000000000000000000000000..8530b7c5cf64572440c05a5539532e245333746f +--- /dev/null ++++ b/src/main/java/org/galemc/gale/tick/step/ServerTickStep.java +@@ -0,0 +1,23 @@ ++// Gale - multithreaded ticking ++ ++package org.galemc.gale.tick.step; ++ ++import net.minecraft.server.level.ServerLevel; ++ ++import java.util.function.Consumer; ++ ++/** ++ * A {@link TickStep} that applies to the whole server (i.e. is run once per tick). ++ * ++ * @author Martijn Muijsers under AGPL-3.0 ++ */ ++public class ServerTickStep extends TickStep { ++ ++ public final Runnable action; ++ ++ ServerTickStep(Runnable action) { ++ super(); ++ this.action = action; ++ } ++ ++} +diff --git a/src/main/java/org/galemc/gale/tick/step/TickStep.java b/src/main/java/org/galemc/gale/tick/step/TickStep.java +new file mode 100644 +index 0000000000000000000000000000000000000000..e07883e4121e3241657f1e60ba46540ab0dd6f08 +--- /dev/null ++++ b/src/main/java/org/galemc/gale/tick/step/TickStep.java +@@ -0,0 +1,14 @@ ++// Gale - multithreaded ticking ++ ++package org.galemc.gale.tick.step; ++ ++/** ++ * An abstract step of ticking, as used in {@link ServerChildrenTickSteps}. ++ * ++ * @author Martijn Muijsers under AGPL-3.0 ++ */ ++public abstract class TickStep { ++ ++ protected TickStep() {} ++ ++} +diff --git a/src/main/java/org/galemc/gale/tick/step/WorldTickStep.java b/src/main/java/org/galemc/gale/tick/step/WorldTickStep.java +new file mode 100644 +index 0000000000000000000000000000000000000000..9c2dddae5f26c4e8db4c7490c23afaf3acb06f2b +--- /dev/null ++++ b/src/main/java/org/galemc/gale/tick/step/WorldTickStep.java +@@ -0,0 +1,23 @@ ++// Gale - multithreaded ticking ++ ++package org.galemc.gale.tick.step; ++ ++import net.minecraft.server.level.ServerLevel; ++ ++import java.util.function.Consumer; ++ ++/** ++ * A {@link TickStep} that applies to each individual world separately. ++ * ++ * @author Martijn Muijsers under AGPL-3.0 ++ */ ++public class WorldTickStep extends TickStep { ++ ++ public final Consumer action; ++ ++ WorldTickStep(Consumer action) { ++ super(); ++ this.action = action; ++ } ++ ++}