From 07ee63724eb56b70e08d91758314a38215d4483e Mon Sep 17 00:00:00 2001 From: MrPowerGamerBR Date: Tue, 28 Nov 2023 02:17:40 -0300 Subject: [PATCH] Improve Fix TE Unload Lag Spike patch --- ...16-Fix-MC-117075-TE-Unload-Lag-Spike.patch | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/patches/server/0016-Fix-MC-117075-TE-Unload-Lag-Spike.patch b/patches/server/0016-Fix-MC-117075-TE-Unload-Lag-Spike.patch index 25f1383..d259730 100644 --- a/patches/server/0016-Fix-MC-117075-TE-Unload-Lag-Spike.patch +++ b/patches/server/0016-Fix-MC-117075-TE-Unload-Lag-Spike.patch @@ -49,12 +49,13 @@ index ddb618fce875b1a337b139c9c47433453654017b..f50a66841fd8c798cd881612be302c29 co.aikar.timings.TimingHistory.tileEntityTicks += this.blockEntityTickers.size(); // Paper diff --git a/src/main/java/net/sparklypower/sparklypaper/BlockEntityTickersList.java b/src/main/java/net/sparklypower/sparklypaper/BlockEntityTickersList.java new file mode 100644 -index 0000000000000000000000000000000000000000..e00d27afc53f4d0f5bacdd81e06b81d231e512ff +index 0000000000000000000000000000000000000000..ebefc70ea5841526f4a4d5111b906d2075967e62 --- /dev/null +++ b/src/main/java/net/sparklypower/sparklypaper/BlockEntityTickersList.java -@@ -0,0 +1,95 @@ +@@ -0,0 +1,100 @@ +package net.sparklypower.sparklypaper; + ++import it.unimi.dsi.fastutil.ints.IntOpenHashSet; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.minecraft.world.level.block.entity.TickingBlockEntity; + @@ -73,8 +74,8 @@ index 0000000000000000000000000000000000000000..e00d27afc53f4d0f5bacdd81e06b81d2 + + * since we don't need to resize the array every single remove. + + */ +public class BlockEntityTickersList extends ObjectArrayList { -+ private final HashSet toRemove = new HashSet<>(); // For some reason, Java's HashSet seems to be faster than fastutil's only if we are removing HUGE amounts of tile entities, idk why -+ private int startSearchFromIndex = Integer.MAX_VALUE; ++ private final IntOpenHashSet toRemove = new IntOpenHashSet(); ++ private int startSearchFromIndex = -1; + + /** Creates a new array list with {@link #DEFAULT_INITIAL_CAPACITY} capacity. */ + public BlockEntityTickersList() { @@ -93,12 +94,12 @@ index 0000000000000000000000000000000000000000..e00d27afc53f4d0f5bacdd81e06b81d2 + /** + * Marks an entry as removed + * -+ * @param index ++ * @param index the index of the item on the list to be marked as removed + */ + public void markAsRemoved(final int index) { -+ if (this.startSearchFromIndex > index) { ++ // The block entities list always loop starting from 0, so we only need to check if the startSearchFromIndex is -1 and that's it ++ if (this.startSearchFromIndex == -1) + this.startSearchFromIndex = index; -+ } + this.toRemove.add(index); + } + @@ -106,24 +107,30 @@ index 0000000000000000000000000000000000000000..e00d27afc53f4d0f5bacdd81e06b81d2 + * Removes elements that have been marked as removed. + */ + public void removeMarkedEntries() { -+ if (this.startSearchFromIndex == Integer.MAX_VALUE) // No entries in the list, skip ++ if (this.startSearchFromIndex == -1) // No entries in the list, skip + return; + + removeAllByIndex(startSearchFromIndex, toRemove); + toRemove.clear(); -+ this.startSearchFromIndex = Integer.MAX_VALUE; // Reset the start search index ++ this.startSearchFromIndex = -1; // Reset the start search index + } + -+ public boolean removeAllByIndex(final int startSearchFromIndex, final Set c) { ++ /** ++ * Removes elements by their index. ++ */ ++ private void removeAllByIndex(final int startSearchFromIndex, final IntOpenHashSet c) { // can't use Set because we want to avoid autoboxing when using contains + final int requiredMatches = c.size(); + if (requiredMatches == 0) -+ return false; // exit early, we don't need to do anything ++ return; // exit early, we don't need to do anything + + final Object[] a = this.a; + int j = startSearchFromIndex; + int matches = 0; + for (int i = startSearchFromIndex; i < size; i++) { // If the user knows the first index to be removed, we can skip a lot of unnecessary comparsions + if (!c.contains(i)) { ++ // TODO: It can be possible to optimize this loop by tracking the start/finish and then using arraycopy to "skip" the elements, ++ // this would optimize cases where the index to be removed are far apart, HOWEVER it does have a big performance impact if you are doing ++ // "arraycopy" for each element + a[j++] = a[i]; + } else { + matches++; @@ -143,8 +150,6 @@ index 0000000000000000000000000000000000000000..e00d27afc53f4d0f5bacdd81e06b81d2 + } + } + Arrays.fill(a, j, size, null); -+ final boolean modified = size != j; + size = j; -+ return modified; + } +}