From 68ec946c7a84c6d5850eb29c564cc85581203057 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Wed, 25 Mar 2020 12:56:18 -0700 Subject: [PATCH] Fix memory leak in TickListServer (#3068) Only occurred when entries were scheduled with huge tick delays Add two flags to debug excessive tick delays: -Dpaper.ticklist-warn-on-excessive-delay=true (false by default) and -Dpaper.ticklist-excessive-delay-threshold=ticks which sets the excessive tick delay to the specified ticks (defaults to 60 * 20 ticks, aka 60 seconds) --- ...imise-TickListServer-by-rewriting-it.patch | 49 +++++++++++++------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/Spigot-Server-Patches/0450-Optimise-TickListServer-by-rewriting-it.patch b/Spigot-Server-Patches/0450-Optimise-TickListServer-by-rewriting-it.patch index 4152a6ffe9..c0a73f35df 100644 --- a/Spigot-Server-Patches/0450-Optimise-TickListServer-by-rewriting-it.patch +++ b/Spigot-Server-Patches/0450-Optimise-TickListServer-by-rewriting-it.patch @@ -1,4 +1,4 @@ -From cfd5fdb1c2d74d13459f23ff6cdf593cd1e293c9 Mon Sep 17 00:00:00 2001 +From ba1ce65d933700f100d6156e3b8c1c617f8de19d Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Fri, 14 Feb 2020 01:24:39 -0800 Subject: [PATCH] Optimise TickListServer by rewriting it @@ -35,12 +35,18 @@ Long scheduled is handled the same as TickListServer. into a map of entries for that chunk. Once the chunk is moved to ticking, the items are re-scheduled. +This patch has also added two flags to debug excessive tick delays: +-Dpaper.ticklist-warn-on-excessive-delay=true (false by default) +and -Dpaper.ticklist-excessive-delay-threshold=ticks which +sets the excessive tick delay to the specified ticks (defaults to +60 * 20 ticks, aka 60 seconds) + diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java new file mode 100644 -index 000000000..666f49fe9 +index 0000000000..e948012d5b --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/server/ticklist/PaperTickList.java -@@ -0,0 +1,602 @@ +@@ -0,0 +1,617 @@ +package com.destroystokyo.paper.server.ticklist; + +import net.minecraft.server.MCUtil; @@ -84,7 +90,7 @@ index 000000000..666f49fe9 + public static final int STATE_TICKED = 1 << 4; // after this, it gets thrown back to unscheduled + public static final int STATE_CANCELLED_TICK = 1 << 5; // still gets moved to unscheduled after tick + -+ private static final int SHORT_SCHEDULE_TICK_THRESHOLD = 20 * 5 + 1; // 5 seconds ++ private static final int SHORT_SCHEDULE_TICK_THRESHOLD = 20 * 20 + 1; // 20 seconds + + private final WorldServer world; + private final Predicate excludeFromScheduling; @@ -117,6 +123,9 @@ index 000000000..666f49fe9 + + private long nextTick; + ++ private static final boolean WARN_ON_EXCESSIVE_DELAY = Boolean.getBoolean("paper.ticklist-warn-on-excessive-delay"); ++ private static final long EXCESSIVE_DELAY_THRESHOLD = Long.getLong("paper.ticklist-excessive-delay-threshold", 60 * 20).longValue(); // 1 min dfl ++ + // assume index < length + private static int getWrappedIndex(final int start, final int length, final int index) { + final int next = start + index; @@ -221,6 +230,11 @@ index 000000000..666f49fe9 + this.pendingChunkTickLoad.remove(chunkKey); + } + } ++ ++ long delay = entry.getTargetTick() - this.nextTick; ++ if (delay >= SHORT_SCHEDULE_TICK_THRESHOLD) { ++ this.longScheduled.remove(entry); ++ } + } + + public void onChunkSetTicking(final int chunkX, final int chunkZ) { @@ -449,6 +463,13 @@ index 000000000..666f49fe9 + return; + } + ++ if (WARN_ON_EXCESSIVE_DELAY) { ++ final long delay = entry.getTargetTick() - this.nextTick; ++ if (delay >= EXCESSIVE_DELAY_THRESHOLD) { ++ MinecraftServer.LOGGER.warn("Entry " + entry.toString() + " has been scheduled with an excessive delay of: " + delay, new Throwable()); ++ } ++ } ++ + final long blockKey = MCUtil.getBlockKey(pos); + + final ArrayList> currentEntries = this.entriesByBlock.computeIfAbsent(blockKey, (long keyInMap) -> new ArrayList<>(3)); @@ -645,7 +666,7 @@ index 000000000..666f49fe9 +} diff --git a/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java new file mode 100644 -index 000000000..13cf1a55a +index 0000000000..13cf1a55a9 --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/server/ticklist/TickListServerInterval.java @@ -0,0 +1,41 @@ @@ -692,7 +713,7 @@ index 000000000..13cf1a55a +} diff --git a/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java b/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java new file mode 100644 -index 000000000..118988c39 +index 0000000000..118988c39e --- /dev/null +++ b/src/main/java/com/destroystokyo/paper/util/set/LinkedSortedSet.java @@ -0,0 +1,142 @@ @@ -839,7 +860,7 @@ index 000000000..118988c39 + } +} diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java -index e650a2e48..2d07d350d 100644 +index e650a2e48d..2d07d350d2 100644 --- a/src/main/java/net/minecraft/server/BlockPosition.java +++ b/src/main/java/net/minecraft/server/BlockPosition.java @@ -125,6 +125,7 @@ public class BlockPosition extends BaseBlockPosition implements MinecraftSeriali @@ -851,7 +872,7 @@ index e650a2e48..2d07d350d 100644 return this.b(baseblockposition.getX(), baseblockposition.getY(), baseblockposition.getZ()); } diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index a385a473a..82168b6ae 100644 +index 8412feef6b..1dcd0980ec 100644 --- a/src/main/java/net/minecraft/server/ChunkProviderServer.java +++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java @@ -119,6 +119,13 @@ public class ChunkProviderServer extends IChunkProvider { @@ -869,7 +890,7 @@ index a385a473a..82168b6ae 100644 public ChunkProviderServer(WorldServer worldserver, File file, DataFixer datafixer, DefinedStructureManager definedstructuremanager, Executor executor, ChunkGenerator chunkgenerator, int i, WorldLoadListener worldloadlistener, Supplier supplier) { this.world = worldserver; diff --git a/src/main/java/net/minecraft/server/NextTickListEntry.java b/src/main/java/net/minecraft/server/NextTickListEntry.java -index 33cfeabde..2287e47d1 100644 +index 33cfeabdee..2287e47d1b 100644 --- a/src/main/java/net/minecraft/server/NextTickListEntry.java +++ b/src/main/java/net/minecraft/server/NextTickListEntry.java @@ -5,11 +5,13 @@ import java.util.Comparator; @@ -940,7 +961,7 @@ index 33cfeabde..2287e47d1 100644 public String toString() { return this.e + ": " + this.a + ", " + this.b + ", " + this.c + ", " + this.f; diff --git a/src/main/java/net/minecraft/server/PlayerChunk.java b/src/main/java/net/minecraft/server/PlayerChunk.java -index b38bc6775..9f8818c2d 100644 +index b38bc67758..9f8818c2d4 100644 --- a/src/main/java/net/minecraft/server/PlayerChunk.java +++ b/src/main/java/net/minecraft/server/PlayerChunk.java @@ -474,7 +474,9 @@ public class PlayerChunk { @@ -955,7 +976,7 @@ index b38bc6775..9f8818c2d 100644 } }); diff --git a/src/main/java/net/minecraft/server/StructureBoundingBox.java b/src/main/java/net/minecraft/server/StructureBoundingBox.java -index dbb565e74..185658e23 100644 +index dbb565e74d..185658e230 100644 --- a/src/main/java/net/minecraft/server/StructureBoundingBox.java +++ b/src/main/java/net/minecraft/server/StructureBoundingBox.java @@ -4,12 +4,12 @@ import com.google.common.base.MoreObjects; @@ -994,7 +1015,7 @@ index dbb565e74..185658e23 100644 return baseblockposition.getX() >= this.a && baseblockposition.getX() <= this.d && baseblockposition.getZ() >= this.c && baseblockposition.getZ() <= this.f && baseblockposition.getY() >= this.b && baseblockposition.getY() <= this.e; } diff --git a/src/main/java/net/minecraft/server/TickListServer.java b/src/main/java/net/minecraft/server/TickListServer.java -index f533860bb..3f1aa5ced 100644 +index f533860bbe..3f1aa5ced6 100644 --- a/src/main/java/net/minecraft/server/TickListServer.java +++ b/src/main/java/net/minecraft/server/TickListServer.java @@ -42,6 +42,11 @@ public class TickListServer implements TickList { @@ -1117,7 +1138,7 @@ index f533860bb..3f1aa5ced 100644 } } diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index c74b85917..3e5ed2bd4 100644 +index aa01f47c08..2de48e7537 100644 --- a/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java @@ -170,6 +170,13 @@ public class WorldServer extends World { @@ -1148,5 +1169,5 @@ index c74b85917..3e5ed2bd4 100644 }, IRegistry.FLUID::getKey, IRegistry.FLUID::get, this::a, "Fluids"); // Paper - Timings this.navigators = Sets.newHashSet(); -- -2.25.1 +2.25.2