Move Connection tick to after world tick

The world tick will synchronise block data to clients. If
the connection tick is ran before, then the server will
send the block ack before the block updates - which causes
the client to think that any blocks it broke/placed
were rejected.

Fixes https://github.com/PaperMC/Folia/issues/194
This commit is contained in:
Spottedleaf 2024-02-21 16:23:51 -08:00
parent 7f0a317854
commit e97b1eee63
3 changed files with 59 additions and 63 deletions

View File

@ -1638,7 +1638,7 @@ index 15ee41452992714108efe53b708b5a4e1da7c1ff..5bef4f50082e56b89239cfd62dd74299
} }
diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java
index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07bd11f0d56 100644 index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..67bf841878eb8e3703782caeb16db4803d13f0d9 100644
--- a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java --- a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java
+++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java +++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java
@@ -53,6 +53,14 @@ import java.util.concurrent.atomic.AtomicReference; @@ -53,6 +53,14 @@ import java.util.concurrent.atomic.AtomicReference;
@ -1656,7 +1656,7 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
public final class ChunkHolderManager { public final class ChunkHolderManager {
private static final Logger LOGGER = LogUtils.getClassLogger(); private static final Logger LOGGER = LogUtils.getClassLogger();
@@ -112,27 +120,92 @@ public final class ChunkHolderManager { @@ -112,27 +120,83 @@ public final class ChunkHolderManager {
private final ChunkTaskScheduler taskScheduler; private final ChunkTaskScheduler taskScheduler;
private long currentTick; private long currentTick;
@ -1666,15 +1666,6 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
- return 0; - return 0;
+ // Folia start - region threading + // Folia start - region threading
+ public static final class HolderManagerRegionData { + public static final class HolderManagerRegionData {
+ /*
+ * This region data is a bit of a mess, because it is part global state and part region state.
+ * Typically for region state we do not need to worry about threading concerns because it is only
+ * accessed by the current region when ticking. But since this contains state (
+ * tickets, and removeTickToChunkExpireTicketCount) that can be written to by any thread holding the
+ * ticket lock, the merge logic is complicated as merging only holds the region lock. So, Folia has modified
+ * the add and remove ticket functions to acquire the region lock if the current region does not own the target
+ * position.
+ */
+ private final ArrayDeque<NewChunkHolder> pendingFullLoadUpdate = new ArrayDeque<>(); + private final ArrayDeque<NewChunkHolder> pendingFullLoadUpdate = new ArrayDeque<>();
+ private final ObjectRBTreeSet<NewChunkHolder> autoSaveQueue = new ObjectRBTreeSet<>((final NewChunkHolder c1, final NewChunkHolder c2) -> { + private final ObjectRBTreeSet<NewChunkHolder> autoSaveQueue = new ObjectRBTreeSet<>((final NewChunkHolder c1, final NewChunkHolder c2) -> {
+ if (c1 == c2) { + if (c1 == c2) {
@ -1716,9 +1707,7 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
+ for (final NewChunkHolder fullLoadUpdate : this.pendingFullLoadUpdate) { + for (final NewChunkHolder fullLoadUpdate : this.pendingFullLoadUpdate) {
+ final int regionCoordinateX = fullLoadUpdate.chunkX >> chunkToRegionShift; + final int regionCoordinateX = fullLoadUpdate.chunkX >> chunkToRegionShift;
+ final int regionCoordinateZ = fullLoadUpdate.chunkZ >> chunkToRegionShift; + final int regionCoordinateZ = fullLoadUpdate.chunkZ >> chunkToRegionShift;
+
- if (saveTickCompare != 0) {
- return saveTickCompare;
+ final HolderManagerRegionData data = regionToData.get(CoordinateUtils.getChunkKey(regionCoordinateX, regionCoordinateZ)); + final HolderManagerRegionData data = regionToData.get(CoordinateUtils.getChunkKey(regionCoordinateX, regionCoordinateZ));
+ if (data != null) { + if (data != null) {
+ data.pendingFullLoadUpdate.add(fullLoadUpdate); + data.pendingFullLoadUpdate.add(fullLoadUpdate);
@ -1728,7 +1717,9 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
+ for (final NewChunkHolder autoSave : this.autoSaveQueue) { + for (final NewChunkHolder autoSave : this.autoSaveQueue) {
+ final int regionCoordinateX = autoSave.chunkX >> chunkToRegionShift; + final int regionCoordinateX = autoSave.chunkX >> chunkToRegionShift;
+ final int regionCoordinateZ = autoSave.chunkZ >> chunkToRegionShift; + final int regionCoordinateZ = autoSave.chunkZ >> chunkToRegionShift;
+
- if (saveTickCompare != 0) {
- return saveTickCompare;
+ final HolderManagerRegionData data = regionToData.get(CoordinateUtils.getChunkKey(regionCoordinateX, regionCoordinateZ)); + final HolderManagerRegionData data = regionToData.get(CoordinateUtils.getChunkKey(regionCoordinateX, regionCoordinateZ));
+ if (data != null) { + if (data != null) {
+ data.autoSaveQueue.add(autoSave); + data.autoSaveQueue.add(autoSave);
@ -1762,7 +1753,7 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
public ChunkHolderManager(final ServerLevel world, final ChunkTaskScheduler taskScheduler) { public ChunkHolderManager(final ServerLevel world, final ChunkTaskScheduler taskScheduler) {
this.world = world; this.world = world;
@@ -167,8 +240,13 @@ public final class ChunkHolderManager { @@ -167,8 +231,13 @@ public final class ChunkHolderManager {
} }
public void close(final boolean save, final boolean halt) { public void close(final boolean save, final boolean halt) {
@ -1777,7 +1768,7 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
LOGGER.info("Waiting 60s for chunk system to halt for world '" + this.world.getWorld().getName() + "'"); LOGGER.info("Waiting 60s for chunk system to halt for world '" + this.world.getWorld().getName() + "'");
if (!this.taskScheduler.halt(true, TimeUnit.SECONDS.toNanos(60L))) { if (!this.taskScheduler.halt(true, TimeUnit.SECONDS.toNanos(60L))) {
LOGGER.warn("Failed to halt world generation/loading tasks for world '" + this.world.getWorld().getName() + "'"); LOGGER.warn("Failed to halt world generation/loading tasks for world '" + this.world.getWorld().getName() + "'");
@@ -178,9 +256,10 @@ public final class ChunkHolderManager { @@ -178,9 +247,10 @@ public final class ChunkHolderManager {
} }
if (save) { if (save) {
@ -1789,7 +1780,7 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
if (this.world.chunkDataControllerNew.hasTasks() || this.world.entityDataControllerNew.hasTasks() || this.world.poiDataControllerNew.hasTasks()) { if (this.world.chunkDataControllerNew.hasTasks() || this.world.entityDataControllerNew.hasTasks() || this.world.poiDataControllerNew.hasTasks()) {
RegionFileIOThread.flush(); RegionFileIOThread.flush();
} }
@@ -201,27 +280,34 @@ public final class ChunkHolderManager { @@ -201,27 +271,34 @@ public final class ChunkHolderManager {
} catch (final IOException ex) { } catch (final IOException ex) {
LOGGER.error("Failed to close poi regionfile cache for world '" + this.world.getWorld().getName() + "'", ex); LOGGER.error("Failed to close poi regionfile cache for world '" + this.world.getWorld().getName() + "'", ex);
} }
@ -1831,7 +1822,7 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
holder.lastAutoSave = currentTick; holder.lastAutoSave = currentTick;
if (holder.save(false, false) != null) { if (holder.save(false, false) != null) {
@@ -235,15 +321,38 @@ public final class ChunkHolderManager { @@ -235,15 +312,38 @@ public final class ChunkHolderManager {
for (final NewChunkHolder holder : reschedule) { for (final NewChunkHolder holder : reschedule) {
if (holder.getChunkStatus().isOrAfter(FullChunkStatus.FULL)) { if (holder.getChunkStatus().isOrAfter(FullChunkStatus.FULL)) {
@ -1873,7 +1864,7 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
LOGGER.info("Saving all chunkholders for world '" + this.world.getWorld().getName() + "'"); LOGGER.info("Saving all chunkholders for world '" + this.world.getWorld().getName() + "'");
} }
@@ -251,7 +360,7 @@ public final class ChunkHolderManager { @@ -251,7 +351,7 @@ public final class ChunkHolderManager {
int saved = 0; int saved = 0;
@ -1882,7 +1873,7 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
long lastLog = start; long lastLog = start;
boolean needsFlush = false; boolean needsFlush = false;
final int flushInterval = 50; final int flushInterval = 50;
@@ -262,6 +371,12 @@ public final class ChunkHolderManager { @@ -262,6 +362,12 @@ public final class ChunkHolderManager {
for (int i = 0, len = holders.size(); i < len; ++i) { for (int i = 0, len = holders.size(); i < len; ++i) {
final NewChunkHolder holder = holders.get(i); final NewChunkHolder holder = holders.get(i);
@ -1895,7 +1886,7 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
try { try {
final NewChunkHolder.SaveStat saveStat = holder.save(shutdown, false); final NewChunkHolder.SaveStat saveStat = holder.save(shutdown, false);
if (saveStat != null) { if (saveStat != null) {
@@ -294,7 +409,7 @@ public final class ChunkHolderManager { @@ -294,7 +400,7 @@ public final class ChunkHolderManager {
} }
} }
} }
@ -1904,7 +1895,7 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
RegionFileIOThread.flush(); RegionFileIOThread.flush();
if (this.world.paperConfig().chunks.flushRegionsOnSave) { if (this.world.paperConfig().chunks.flushRegionsOnSave) {
try { try {
@@ -707,6 +822,13 @@ public final class ChunkHolderManager { @@ -707,6 +813,13 @@ public final class ChunkHolderManager {
} }
public void tick() { public void tick() {
@ -1918,7 +1909,7 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
final int sectionShift = this.world.getRegionChunkShift(); final int sectionShift = this.world.getRegionChunkShift();
final Predicate<Ticket<?>> expireNow = (final Ticket<?> ticket) -> { final Predicate<Ticket<?>> expireNow = (final Ticket<?> ticket) -> {
@@ -716,12 +838,12 @@ public final class ChunkHolderManager { @@ -716,12 +829,12 @@ public final class ChunkHolderManager {
return --ticket.removeDelay <= 0L; return --ticket.removeDelay <= 0L;
}; };
@ -1936,7 +1927,7 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
continue; continue;
} }
@@ -1024,19 +1146,51 @@ public final class ChunkHolderManager { @@ -1024,19 +1137,51 @@ public final class ChunkHolderManager {
if (changedFullStatus.isEmpty()) { if (changedFullStatus.isEmpty()) {
return; return;
} }
@ -2000,7 +1991,7 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
} }
} }
} }
@@ -1044,8 +1198,9 @@ public final class ChunkHolderManager { @@ -1044,8 +1189,9 @@ public final class ChunkHolderManager {
private void removeChunkHolder(final NewChunkHolder holder) { private void removeChunkHolder(final NewChunkHolder holder) {
holder.killed = true; holder.killed = true;
holder.vanillaChunkHolder.onChunkRemove(); holder.vanillaChunkHolder.onChunkRemove();
@ -2011,7 +2002,7 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
synchronized (this.chunkHolders) { synchronized (this.chunkHolders) {
this.chunkHolders.remove(CoordinateUtils.getChunkKey(holder.chunkX, holder.chunkZ)); this.chunkHolders.remove(CoordinateUtils.getChunkKey(holder.chunkX, holder.chunkZ));
} }
@@ -1059,7 +1214,7 @@ public final class ChunkHolderManager { @@ -1059,7 +1205,7 @@ public final class ChunkHolderManager {
throw new IllegalStateException("Cannot unload chunks recursively"); throw new IllegalStateException("Cannot unload chunks recursively");
} }
final int sectionShift = this.unloadQueue.coordinateShift; // sectionShift <= lock shift final int sectionShift = this.unloadQueue.coordinateShift; // sectionShift <= lock shift
@ -2020,7 +2011,7 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
int unloadCountTentative = 0; int unloadCountTentative = 0;
for (final ChunkQueue.SectionToUnload sectionRef : unloadSectionsForRegion) { for (final ChunkQueue.SectionToUnload sectionRef : unloadSectionsForRegion) {
final ChunkQueue.UnloadSection section final ChunkQueue.UnloadSection section
@@ -1372,7 +1527,13 @@ public final class ChunkHolderManager { @@ -1372,7 +1518,13 @@ public final class ChunkHolderManager {
// only call on tick thread // only call on tick thread
protected final boolean processPendingFullUpdate() { protected final boolean processPendingFullUpdate() {
@ -2035,7 +2026,7 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
boolean ret = false; boolean ret = false;
@@ -1383,9 +1544,7 @@ public final class ChunkHolderManager { @@ -1383,9 +1535,7 @@ public final class ChunkHolderManager {
ret |= holder.handleFullStatusChange(changedFullStatus); ret |= holder.handleFullStatusChange(changedFullStatus);
if (!changedFullStatus.isEmpty()) { if (!changedFullStatus.isEmpty()) {
@ -2046,7 +2037,7 @@ index 6bc7c6f16a1649fc9e24e7cf90fca401e5bd4875..30259130f23dc07288a7cbb33456b07b
changedFullStatus.clear(); changedFullStatus.clear();
} }
} }
@@ -1399,7 +1558,7 @@ public final class ChunkHolderManager { @@ -1399,7 +1549,7 @@ public final class ChunkHolderManager {
private JsonObject getDebugJsonNoLock() { private JsonObject getDebugJsonNoLock() {
final JsonObject ret = new JsonObject(); final JsonObject ret = new JsonObject();
@ -10075,7 +10066,7 @@ index 3e2d5dcd62775b6ed7c0ce0ba51a71b635b1d644..98fb69a9adeb6eaab199aec127692acb
// CraftBukkit start - SPIGOT-5477, MC-142590 // CraftBukkit start - SPIGOT-5477, MC-142590
} else if (MinecraftServer.getServer().hasStopped() || (listener instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) listener).processedDisconnect)) { } else if (MinecraftServer.getServer().hasStopped() || (listener instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) listener).processedDisconnect)) {
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d742a4dc0ac 100644 index 680919045310be7e50e2d503a23d265f2e9b2bc6..11eb550cba3a8eee1deb2f00e5514863e255ea07 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java --- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -203,7 +203,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -203,7 +203,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@ -10479,7 +10470,7 @@ index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d74
this.getProfiler().incrementCounter("runTask"); this.getProfiler().incrementCounter("runTask");
super.doRunTask(ticktask); super.doRunTask(ticktask);
} }
@@ -1497,43 +1578,85 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1497,43 +1578,83 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return false; return false;
} }
@ -10536,8 +10527,6 @@ index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d74
+ bukkit.taskScheduler.executeTick(); + bukkit.taskScheduler.executeTick();
+ } + }
+ } + }
+ // now tick connections
+ region.world.getCurrentWorldData().tickConnections(); // Folia - region threading
+ } + }
+ // Folia end - region threading + // Folia end - region threading
@ -10576,7 +10565,7 @@ index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d74
} }
} }
} finally { } finally {
@@ -1543,63 +1666,37 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1543,63 +1664,37 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Paper end - Incremental chunk and player saving // Paper end - Incremental chunk and player saving
io.papermc.paper.util.CachedLists.reset(); // Paper io.papermc.paper.util.CachedLists.reset(); // Paper
// Paper start - move executeAll() into full server tick timing // Paper start - move executeAll() into full server tick timing
@ -10652,7 +10641,7 @@ index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d74
private ServerStatus buildServerStatus() { private ServerStatus buildServerStatus() {
ServerStatus.Players serverping_serverpingplayersample = this.buildPlayerStatus(); ServerStatus.Players serverping_serverpingplayersample = this.buildPlayerStatus();
@@ -1607,7 +1704,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1607,7 +1702,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} }
private ServerStatus.Players buildPlayerStatus() { private ServerStatus.Players buildPlayerStatus() {
@ -10661,7 +10650,7 @@ index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d74
int i = this.getMaxPlayers(); int i = this.getMaxPlayers();
if (this.hidesOnlinePlayers()) { if (this.hidesOnlinePlayers()) {
@@ -1628,31 +1725,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1628,31 +1723,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} }
} }
@ -10699,7 +10688,7 @@ index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d74
MinecraftTimings.commandFunctionsTimer.stopTiming(); // Spigot // Paper MinecraftTimings.commandFunctionsTimer.stopTiming(); // Spigot // Paper
this.profiler.popPush("levels"); this.profiler.popPush("levels");
//Iterator iterator = this.getAllLevels().iterator(); // Paper - Throw exception on world create while being ticked; moved down //Iterator iterator = this.getAllLevels().iterator(); // Paper - Throw exception on world create while being ticked; moved down
@@ -1660,7 +1744,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1660,7 +1742,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// CraftBukkit start // CraftBukkit start
// Run tasks that are waiting on processing // Run tasks that are waiting on processing
MinecraftTimings.processQueueTimer.startTiming(); // Spigot MinecraftTimings.processQueueTimer.startTiming(); // Spigot
@ -10708,7 +10697,7 @@ index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d74
this.processQueue.remove().run(); this.processQueue.remove().run();
} }
MinecraftTimings.processQueueTimer.stopTiming(); // Spigot MinecraftTimings.processQueueTimer.stopTiming(); // Spigot
@@ -1668,13 +1752,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1668,13 +1750,13 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
MinecraftTimings.timeUpdateTimer.startTiming(); // Spigot // Paper MinecraftTimings.timeUpdateTimer.startTiming(); // Spigot // Paper
// Send time updates to everyone, it will get the right time from the world the player is in. // Send time updates to everyone, it will get the right time from the world the player is in.
// Paper start - Perf: Optimize time updates // Paper start - Perf: Optimize time updates
@ -10725,7 +10714,7 @@ index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d74
continue; continue;
} }
ServerPlayer entityplayer = (ServerPlayer) entityhuman; ServerPlayer entityplayer = (ServerPlayer) entityhuman;
@@ -1687,14 +1771,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1687,14 +1769,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Paper end - Perf: Optimize time updates // Paper end - Perf: Optimize time updates
MinecraftTimings.timeUpdateTimer.stopTiming(); // Spigot // Paper MinecraftTimings.timeUpdateTimer.stopTiming(); // Spigot // Paper
@ -10743,7 +10732,7 @@ index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d74
this.profiler.push(() -> { this.profiler.push(() -> {
return worldserver + " " + worldserver.dimension().location(); return worldserver + " " + worldserver.dimension().location();
@@ -1711,7 +1792,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1711,7 +1790,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
try { try {
worldserver.timings.doTick.startTiming(); // Spigot worldserver.timings.doTick.startTiming(); // Spigot
@ -10752,7 +10741,7 @@ index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d74
// Paper start // Paper start
for (final io.papermc.paper.chunk.SingleThreadChunkRegionManager regionManager : worldserver.getChunkSource().chunkMap.regionManagers) { for (final io.papermc.paper.chunk.SingleThreadChunkRegionManager regionManager : worldserver.getChunkSource().chunkMap.regionManagers) {
regionManager.recalculateRegions(); regionManager.recalculateRegions();
@@ -1727,17 +1808,17 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1727,17 +1806,18 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.profiler.pop(); this.profiler.pop();
this.profiler.pop(); this.profiler.pop();
@ -10765,7 +10754,8 @@ index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d74
this.profiler.popPush("connection"); this.profiler.popPush("connection");
MinecraftTimings.connectionTimer.startTiming(); // Spigot // Paper MinecraftTimings.connectionTimer.startTiming(); // Spigot // Paper
- this.getConnection().tick(); - this.getConnection().tick();
+ if (region == null) this.getConnection().tick(); // Folia - region threading - moved into post entity scheduler tick + if (region == null) this.getConnection().tick(); // Folia - region threading
+ if (region != null) regionizedWorldData.tickConnections(); // Folia - region threading
MinecraftTimings.connectionTimer.stopTiming(); // Spigot // Paper MinecraftTimings.connectionTimer.stopTiming(); // Spigot // Paper
this.profiler.popPush("players"); this.profiler.popPush("players");
MinecraftTimings.playerListTimer.startTiming(); // Spigot // Paper MinecraftTimings.playerListTimer.startTiming(); // Spigot // Paper
@ -10774,7 +10764,7 @@ index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d74
MinecraftTimings.playerListTimer.stopTiming(); // Spigot // Paper MinecraftTimings.playerListTimer.stopTiming(); // Spigot // Paper
if (SharedConstants.IS_RUNNING_IN_IDE && this.tickRateManager.runsNormally()) { if (SharedConstants.IS_RUNNING_IN_IDE && this.tickRateManager.runsNormally()) {
GameTestTicker.SINGLETON.tick(); GameTestTicker.SINGLETON.tick();
@@ -1746,7 +1827,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1746,7 +1826,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.profiler.popPush("server gui refresh"); this.profiler.popPush("server gui refresh");
MinecraftTimings.tickablesTimer.startTiming(); // Spigot // Paper MinecraftTimings.tickablesTimer.startTiming(); // Spigot // Paper
@ -10783,7 +10773,7 @@ index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d74
((Runnable) this.tickables.get(i)).run(); ((Runnable) this.tickables.get(i)).run();
} }
MinecraftTimings.tickablesTimer.stopTiming(); // Spigot // Paper MinecraftTimings.tickablesTimer.stopTiming(); // Spigot // Paper
@@ -1754,7 +1835,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1754,7 +1834,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.profiler.popPush("send chunks"); this.profiler.popPush("send chunks");
iterator = this.playerList.getPlayers().iterator(); iterator = this.playerList.getPlayers().iterator();
@ -10792,7 +10782,7 @@ index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d74
ServerPlayer entityplayer = (ServerPlayer) iterator.next(); ServerPlayer entityplayer = (ServerPlayer) iterator.next();
entityplayer.connection.chunkSender.sendNextChunks(entityplayer); entityplayer.connection.chunkSender.sendNextChunks(entityplayer);
@@ -2097,7 +2178,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -2097,7 +2177,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} }
public int getTickCount() { public int getTickCount() {
@ -10801,7 +10791,7 @@ index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d74
} }
public int getSpawnProtectionRadius() { public int getSpawnProtectionRadius() {
@@ -2152,6 +2233,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -2152,6 +2232,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} }
public void invalidateStatus() { public void invalidateStatus() {
@ -10817,7 +10807,7 @@ index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d74
this.lastServerStatus = 0L; this.lastServerStatus = 0L;
} }
@@ -2166,6 +2256,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -2166,6 +2255,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@Override @Override
public void executeIfPossible(Runnable runnable) { public void executeIfPossible(Runnable runnable) {
@ -10825,7 +10815,7 @@ index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d74
if (this.isStopped()) { if (this.isStopped()) {
throw new RejectedExecutionException("Server already shutting down"); throw new RejectedExecutionException("Server already shutting down");
} else { } else {
@@ -2424,7 +2515,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -2424,7 +2514,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} }
public long getAverageTickTimeNanos() { public long getAverageTickTimeNanos() {
@ -10839,7 +10829,7 @@ index 680919045310be7e50e2d503a23d265f2e9b2bc6..0330f180ef8fed3091b69758cea64d74
} }
public long[] getTickTimesNanos() { public long[] getTickTimesNanos() {
@@ -2781,14 +2877,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -2781,14 +2876,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} }
public ProfileResults stopTimeProfiler() { public ProfileResults stopTimeProfiler() {

View File

@ -10,7 +10,7 @@ the impact from scaling the region threads, but is not a fix
to the underlying issue. to the underlying issue.
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 0330f180ef8fed3091b69758cea64d742a4dc0ac..b912a5d6737cf8bd74617225ca0837e6e97b7206 100644 index 11eb550cba3a8eee1deb2f00e5514863e255ea07..39cbb724820a07778191b0421c9ded6a9af1ad04 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java --- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1466,6 +1466,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1466,6 +1466,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa

View File

@ -926,10 +926,10 @@ index 0000000000000000000000000000000000000000..95c0e6416afafbb633f0a30ae22df166
+ ) {} + ) {}
+} +}
diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java diff --git a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java
index 30259130f23dc07288a7cbb33456b07bd11f0d56..a4157bc24c36c63502667d69910108a50114f370 100644 index 67bf841878eb8e3703782caeb16db4803d13f0d9..0d8b2a4127e8c8e4970d220b8a2240490da6e7df 100644
--- a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java --- a/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java
+++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java +++ b/src/main/java/io/papermc/paper/chunk/system/scheduling/ChunkHolderManager.java
@@ -1471,8 +1471,11 @@ public final class ChunkHolderManager { @@ -1462,8 +1462,11 @@ public final class ChunkHolderManager {
} }
public boolean processTicketUpdates() { public boolean processTicketUpdates() {
@ -1376,7 +1376,7 @@ index 98fb69a9adeb6eaab199aec127692acb07f56808..7cc624505931dcb6696c3ef3ee3bbea7
label25: label25:
{ {
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index b912a5d6737cf8bd74617225ca0837e6e97b7206..b73699a08a368e6305759438c00066b0d5e7b39a 100644 index 39cbb724820a07778191b0421c9ded6a9af1ad04..3ec07e77748ee9bb21f9d09230f935bca2217e4d 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java --- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1582,6 +1582,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1582,6 +1582,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@ -1404,7 +1404,7 @@ index b912a5d6737cf8bd74617225ca0837e6e97b7206..b73699a08a368e6305759438c00066b0
for (Entity entity : region.world.getCurrentWorldData().getLocalEntitiesCopy()) { for (Entity entity : region.world.getCurrentWorldData().getLocalEntitiesCopy()) {
if (!io.papermc.paper.util.TickThread.isTickThreadFor(entity) || entity.isRemoved()) { if (!io.papermc.paper.util.TickThread.isTickThreadFor(entity) || entity.isRemoved()) {
continue; continue;
@@ -1627,10 +1634,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1627,8 +1634,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
org.bukkit.craftbukkit.entity.CraftEntity bukkit = entity.getBukkitEntityRaw(); org.bukkit.craftbukkit.entity.CraftEntity bukkit = entity.getBukkitEntityRaw();
if (bukkit != null) { if (bukkit != null) {
bukkit.taskScheduler.executeTick(); bukkit.taskScheduler.executeTick();
@ -1413,14 +1413,10 @@ index b912a5d6737cf8bd74617225ca0837e6e97b7206..b73699a08a368e6305759438c00066b0
} }
+ profiler.addCounter(ca.spottedleaf.leafprofiler.LProfilerRegistry.ENTITY_SCHEDULERS_TICKED, tickedEntitySchedulers); // Folia - profiler + profiler.addCounter(ca.spottedleaf.leafprofiler.LProfilerRegistry.ENTITY_SCHEDULERS_TICKED, tickedEntitySchedulers); // Folia - profiler
+ } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ENTITY_SCHEDULER_TICK); } // Folia - profiler + } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ENTITY_SCHEDULER_TICK); } // Folia - profiler
// now tick connections
+ profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CONNECTION_TICK); try { // Folia - profiler
region.world.getCurrentWorldData().tickConnections(); // Folia - region threading
+ } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CONNECTION_TICK); } // Folia - profiler
} }
// Folia end - region threading // Folia end - region threading
@@ -1650,6 +1662,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1648,6 +1658,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} }
this.profiler.push("save"); this.profiler.push("save");
final boolean fullSave = autosavePeriod > 0 && io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() % autosavePeriod == 0; // Folia - region threading final boolean fullSave = autosavePeriod > 0 && io.papermc.paper.threadedregions.RegionizedServer.getCurrentTick() % autosavePeriod == 0; // Folia - region threading
@ -1428,7 +1424,7 @@ index b912a5d6737cf8bd74617225ca0837e6e97b7206..b73699a08a368e6305759438c00066b0
try { try {
this.isSaving = true; this.isSaving = true;
if (playerSaveInterval > 0) { if (playerSaveInterval > 0) {
@@ -1663,6 +1676,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1661,6 +1672,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} finally { } finally {
this.isSaving = false; this.isSaving = false;
} }
@ -1436,7 +1432,7 @@ index b912a5d6737cf8bd74617225ca0837e6e97b7206..b73699a08a368e6305759438c00066b0
this.profiler.pop(); this.profiler.pop();
// Paper end - Incremental chunk and player saving // Paper end - Incremental chunk and player saving
io.papermc.paper.util.CachedLists.reset(); // Paper io.papermc.paper.util.CachedLists.reset(); // Paper
@@ -1727,6 +1741,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1725,6 +1737,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} }
public void tickChildren(BooleanSupplier shouldKeepTicking, io.papermc.paper.threadedregions.TickRegions.TickRegionData region) { // Folia - region threading public void tickChildren(BooleanSupplier shouldKeepTicking, io.papermc.paper.threadedregions.TickRegions.TickRegionData region) { // Folia - region threading
@ -1444,7 +1440,7 @@ index b912a5d6737cf8bd74617225ca0837e6e97b7206..b73699a08a368e6305759438c00066b0
final io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData(); // Folia - regionised ticking final io.papermc.paper.threadedregions.RegionizedWorldData regionizedWorldData = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData(); // Folia - regionised ticking
if (region == null) this.getPlayerList().getPlayers().forEach((entityplayer) -> { // Folia - region threading if (region == null) this.getPlayerList().getPlayers().forEach((entityplayer) -> { // Folia - region threading
entityplayer.connection.suspendFlushing(); entityplayer.connection.suspendFlushing();
@@ -1793,12 +1808,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @@ -1791,12 +1804,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
try { try {
worldserver.timings.doTick.startTiming(); // Spigot worldserver.timings.doTick.startTiming(); // Spigot
@ -1459,6 +1455,16 @@ index b912a5d6737cf8bd74617225ca0837e6e97b7206..b73699a08a368e6305759438c00066b0
worldserver.timings.doTick.stopTiming(); // Spigot worldserver.timings.doTick.stopTiming(); // Spigot
} catch (Throwable throwable) { } catch (Throwable throwable) {
CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception ticking world"); CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception ticking world");
@@ -1814,7 +1829,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.profiler.popPush("connection");
MinecraftTimings.connectionTimer.startTiming(); // Spigot // Paper
if (region == null) this.getConnection().tick(); // Folia - region threading
+ profiler.startTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CONNECTION_TICK); try { // Folia - profiler
if (region != null) regionizedWorldData.tickConnections(); // Folia - region threading
+ } finally { profiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.CONNECTION_TICK); } // Folia - profiler
MinecraftTimings.connectionTimer.stopTiming(); // Spigot // Paper
this.profiler.popPush("players");
MinecraftTimings.playerListTimer.startTiming(); // Spigot // Paper
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 6aa8595c22ac933a79b25c7bb159343365b70f26..21ec49acb3c1241d9286959c42a7f8363f637e4f 100644 index 6aa8595c22ac933a79b25c7bb159343365b70f26..21ec49acb3c1241d9286959c42a7f8363f637e4f 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java --- a/src/main/java/net/minecraft/server/level/ChunkMap.java