From 6f7ba53119f24258d79c85f767dccef26ace3744 Mon Sep 17 00:00:00 2001 From: NanaChiyo0721 Date: Sat, 22 Aug 2026 23:17:26 +0800 Subject: [PATCH] Optimize iteration in task queue ttl optimization --- ...izedTaskQueue-queue-TTL-optimization.patch | 80 +++++++++++-------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/shiroha-server/minecraft-patches/features/0030-RegionizedTaskQueue-queue-TTL-optimization.patch b/shiroha-server/minecraft-patches/features/0030-RegionizedTaskQueue-queue-TTL-optimization.patch index 1e44909..10ce9a5 100644 --- a/shiroha-server/minecraft-patches/features/0030-RegionizedTaskQueue-queue-TTL-optimization.patch +++ b/shiroha-server/minecraft-patches/features/0030-RegionizedTaskQueue-queue-TTL-optimization.patch @@ -5,7 +5,7 @@ Subject: [PATCH] RegionizedTaskQueue queue TTL optimization diff --git a/io/papermc/paper/threadedregions/RegionizedTaskQueue.java b/io/papermc/paper/threadedregions/RegionizedTaskQueue.java -index 037697e6364c73057b1fbac354bd78d8bf35bc7b..0e88bc2776615f8e3e1e6a05c5ffb8f791d49917 100644 +index 037697e6364c73057b1fbac354bd78d8bf35bc7b..3a7e4b57dc41030295f5e9da58a0fcd1270c521f 100644 --- a/io/papermc/paper/threadedregions/RegionizedTaskQueue.java +++ b/io/papermc/paper/threadedregions/RegionizedTaskQueue.java @@ -23,6 +23,7 @@ import java.util.concurrent.atomic.AtomicLong; @@ -16,7 +16,7 @@ index 037697e6364c73057b1fbac354bd78d8bf35bc7b..0e88bc2776615f8e3e1e6a05c5ffb8f7 public PrioritisedExecutor.PrioritisedTask createChunkTask(final ServerLevel world, final int chunkX, final int chunkZ, final Runnable run) { -@@ -155,6 +156,58 @@ public final class RegionizedTaskQueue { +@@ -155,6 +156,68 @@ public final class RegionizedTaskQueue { } } @@ -30,41 +30,51 @@ index 037697e6364c73057b1fbac354bd78d8bf35bc7b..0e88bc2776615f8e3e1e6a05c5ffb8f7 + + final ReferenceCountData[] toRemoveTicket = new ReferenceCountData[1]; + -+ for (ConcurrentChainedLong2ReferenceHashTable.TableEntry counterEntry : this.referenceCounters.entrySet()) { -+ final long coord = counterEntry.getKey(); -+ final ReferenceCountData counterData = counterEntry.getValue(); ++ final it.unimi.dsi.fastutil.longs.LongIterator sectionsIterator = currentRegion.getOwnedSectionsUnsynchronised(); ++ while (sectionsIterator.hasNext()) { ++ final long sectionKey = sectionsIterator.nextLong(); ++ final int sectionX = CoordinateUtils.getChunkX(sectionKey); ++ final int sectionZ = CoordinateUtils.getChunkZ(sectionKey); + -+ // only tick for our region -+ if (currentRegion == this.world.regioniser.getRegionAtUnsynchronised(CoordinateUtils.getChunkX(coord), CoordinateUtils.getChunkZ(coord))) { -+ long curr = counterData.referenceTTL.get(); -+ // successfully decreased ttl -+ if (curr == (curr = counterData.referenceTTL.compareAndExchange(curr, curr - 1))) { -+ if (counterData.referenceCount.get() != 0L) { -+ // still has reference, pump back -+ counterData.referenceTTL.set(QUEUE_MAX_TTL_TICKS); -+ continue; -+ } ++ final int chunkX = sectionX << this.world.regioniser.sectionChunkShift; ++ final int chunkZ = sectionZ << this.world.regioniser.sectionChunkShift; ++ final long coord = CoordinateUtils.getChunkKey(chunkX, chunkZ); ++ final ReferenceCountData counterData = this.referenceCounters.get(coord); + -+ // dead -+ if (curr <= 0) { -+ // parsed from decrementReference -+ this.referenceCounters.computeIfPresent(coord, (final long keyInMap, final ReferenceCountData valueInMap) -> { -+ // might be increased again -+ if (valueInMap.referenceCount.get() != 0L) { -+ valueInMap.referenceTTL.set(QUEUE_MAX_TTL_TICKS); // still has reference, pump back -+ return valueInMap; // directly, the ttl was already charged in add logic -+ } ++ // removed ++ if (counterData == null) { ++ continue; ++ } + -+ // note: valueInMap may not be referenceCountData -+ toRemoveTicket[0] = valueInMap; ++ // do ttl ++ long curr = counterData.referenceTTL.get(); ++ // successfully decreased ttl ++ if (curr == (curr = counterData.referenceTTL.compareAndExchange(curr, curr - 1))) { ++ if (counterData.referenceCount.get() != 0L) { ++ // still has reference, pump back ++ counterData.referenceTTL.set(QUEUE_MAX_TTL_TICKS); ++ continue; ++ } + -+ return null; -+ }); -+ -+ if (toRemoveTicket[0] != null) { -+ this.removeTicket(coord, toRemoveTicket[0].id); -+ toRemoveTicket[0] = null; ++ // dead ++ if (curr <= 0) { ++ // parsed from decrementReference ++ this.referenceCounters.computeIfPresent(coord, (final long keyInMap, final ReferenceCountData valueInMap) -> { ++ // might be increased again ++ if (valueInMap.referenceCount.get() != 0L) { ++ valueInMap.referenceTTL.set(QUEUE_MAX_TTL_TICKS); // still has reference, pump back ++ return valueInMap; // directly, the ttl was already charged in add logic + } ++ ++ // note: valueInMap may not be referenceCountData ++ toRemoveTicket[0] = valueInMap; ++ ++ return null; ++ }); ++ ++ if (toRemoveTicket[0] != null) { ++ this.removeTicket(coord, toRemoveTicket[0].id); ++ toRemoveTicket[0] = null; + } + } + } @@ -75,7 +85,7 @@ index 037697e6364c73057b1fbac354bd78d8bf35bc7b..0e88bc2776615f8e3e1e6a05c5ffb8f7 private void decrementReference(final ReferenceCountData referenceCountData, final long coord) { if (!referenceCountData.decreaseReferenceCount()) { return; -@@ -212,9 +265,10 @@ public final class RegionizedTaskQueue { +@@ -212,9 +275,10 @@ public final class RegionizedTaskQueue { private final long id = ID_GENERATOR.getAndIncrement(); public final AtomicLong referenceCount = new AtomicLong(1L); @@ -87,7 +97,7 @@ index 037697e6364c73057b1fbac354bd78d8bf35bc7b..0e88bc2776615f8e3e1e6a05c5ffb8f7 public boolean addCount() { int failures = 0; for (long curr = this.referenceCount.get();;) { -@@ -227,6 +281,27 @@ public final class RegionizedTaskQueue { +@@ -227,6 +291,27 @@ public final class RegionizedTaskQueue { } if (curr == (curr = this.referenceCount.compareAndExchange(curr, curr + 1L))) { @@ -115,7 +125,7 @@ index 037697e6364c73057b1fbac354bd78d8bf35bc7b..0e88bc2776615f8e3e1e6a05c5ffb8f7 return true; } -@@ -234,11 +309,11 @@ public final class RegionizedTaskQueue { +@@ -234,11 +319,11 @@ public final class RegionizedTaskQueue { } }