From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Taiyou06 Date: Mon, 14 Apr 2025 14:36:57 +0200 Subject: [PATCH] Optimize ThreadedTicketLevelPropagator diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ThreadedTicketLevelPropagator.java b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ThreadedTicketLevelPropagator.java index b69d256e2f6bab3c1b90c5f8c42caa3d80cd67a4..e8dddc7fca4b0383844be5337a87c4bc1de204b7 100644 --- a/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ThreadedTicketLevelPropagator.java +++ b/ca/spottedleaf/moonrise/patches/chunk_system/scheduling/ThreadedTicketLevelPropagator.java @@ -780,11 +780,13 @@ public abstract class ThreadedTicketLevelPropagator { // minimum number of bits to represent [0, SECTION_SIZE * SECTION_CACHE_WIDTH) private static final int COORDINATE_BITS = 9; private static final int COORDINATE_SIZE = 1 << COORDINATE_BITS; + static { if ((SECTION_SIZE * SECTION_CACHE_WIDTH) > (1 << COORDINATE_BITS)) { throw new IllegalStateException("Adjust COORDINATE_BITS"); } } + // index = x + (z * SECTION_CACHE_WIDTH) // (this requires x >= 0 and z >= 0) private final Section[] sections = new Section[SECTION_CACHE_WIDTH * SECTION_CACHE_WIDTH]; @@ -828,8 +830,8 @@ public abstract class ThreadedTicketLevelPropagator { // must hold ticket lock for (centerSectionX,centerSectionZ) in radius rad // must call setupEncodeOffset private final void setupCaches(final ThreadedTicketLevelPropagator propagator, - final int centerSectionX, final int centerSectionZ, - final int rad) { + final int centerSectionX, final int centerSectionZ, + final int rad) { for (int dz = -rad; dz <= rad; ++dz) { for (int dx = -rad; dx <= rad; ++dx) { final int sectionX = centerSectionX + dx; @@ -847,29 +849,29 @@ public abstract class ThreadedTicketLevelPropagator { } private final void setSectionInCache(final int sectionX, final int sectionZ, final Section section) { - this.sections[sectionX + SECTION_CACHE_WIDTH*sectionZ + this.sectionIndexOffset] = section; + this.sections[sectionX + SECTION_CACHE_WIDTH * sectionZ + this.sectionIndexOffset] = section; } private final Section getSection(final int sectionX, final int sectionZ) { - return this.sections[sectionX + SECTION_CACHE_WIDTH*sectionZ + this.sectionIndexOffset]; + return this.sections[sectionX + SECTION_CACHE_WIDTH * sectionZ + this.sectionIndexOffset]; } private final int getLevel(final int posX, final int posZ) { - final Section section = this.sections[(posX >> SECTION_SHIFT) + SECTION_CACHE_WIDTH*(posZ >> SECTION_SHIFT) + this.sectionIndexOffset]; + final Section section = this.sections[(posX >> SECTION_SHIFT) + SECTION_CACHE_WIDTH * (posZ >> SECTION_SHIFT) + this.sectionIndexOffset]; if (section != null) { - return (int)section.levels[(posX & (SECTION_SIZE - 1)) | ((posZ & (SECTION_SIZE - 1)) << SECTION_SHIFT)] & 0xFF; + return (int) section.levels[(posX & (SECTION_SIZE - 1)) | ((posZ & (SECTION_SIZE - 1)) << SECTION_SHIFT)] & 0xFF; } return 0; } private final void setLevel(final int posX, final int posZ, final int to) { - final Section section = this.sections[(posX >> SECTION_SHIFT) + SECTION_CACHE_WIDTH*(posZ >> SECTION_SHIFT) + this.sectionIndexOffset]; + final Section section = this.sections[(posX >> SECTION_SHIFT) + SECTION_CACHE_WIDTH * (posZ >> SECTION_SHIFT) + this.sectionIndexOffset]; if (section != null) { final int index = (posX & (SECTION_SIZE - 1)) | ((posZ & (SECTION_SIZE - 1)) << SECTION_SHIFT); final short level = section.levels[index]; - section.levels[index] = (short)((level & ~0xFF) | (to & 0xFF)); - this.updatedPositions.put(CoordinateUtils.getChunkKey(posX, posZ), (byte)to); + section.levels[index] = (short) ((level & ~0xFF) | (to & 0xFF)); + this.updatedPositions.put(CoordinateUtils.getChunkKey(posX, posZ), (byte) to); } } @@ -882,8 +884,8 @@ public abstract class ThreadedTicketLevelPropagator { // next LEVEL_BITS (6) bits: propagated level [0, 63] // propagation directions bitset (16 bits): private static final long ALL_DIRECTIONS_BITSET = ( - // z = -1 - (1L << ((1 - 1) | ((1 - 1) << 2))) | + // z = -1 + (1L << ((1 - 1) | ((1 - 1) << 2))) | (1L << ((1 + 0) | ((1 - 1) << 2))) | (1L << ((1 + 1) | ((1 - 1) << 2))) | @@ -920,7 +922,7 @@ public abstract class ThreadedTicketLevelPropagator { } private void ch(long bs, int shift) { - int bitset = (int)(bs >>> shift); + int bitset = (int) (bs >>> shift); for (int i = 0, len = Integer.bitCount(bitset); i < len; ++i) { final int set = Integer.numberOfTrailingZeros(bitset); final int tailingBit = (-bitset) & bitset; @@ -1000,27 +1002,38 @@ public abstract class ThreadedTicketLevelPropagator { final int decodeOffsetZ = -this.encodeOffsetZ; final int encodeOffset = this.coordinateOffset; final int sectionOffset = this.sectionIndexOffset; + final Section[] sectionsArray = this.sections; final Long2ByteLinkedOpenHashMap updatedPositions = this.updatedPositions; while (queueReadIndex < queueLength) { final long queueValue = queue[queueReadIndex++]; - final int posX = ((int)queueValue & (COORDINATE_SIZE - 1)) + decodeOffsetX; - final int posZ = (((int)queueValue >>> COORDINATE_BITS) & (COORDINATE_SIZE - 1)) + decodeOffsetZ; - final int propagatedLevel = ((int)queueValue >>> (COORDINATE_BITS + COORDINATE_BITS)) & (LEVEL_COUNT - 1); + final int posX = ((int) queueValue & (COORDINATE_SIZE - 1)) + decodeOffsetX; + final int posZ = (((int) queueValue >>> COORDINATE_BITS) & (COORDINATE_SIZE - 1)) + decodeOffsetZ; + final int propagatedLevel = ((int) queueValue >>> (COORDINATE_BITS + COORDINATE_BITS)) & (LEVEL_COUNT - 1); // note: the above code requires coordinate bits * 2 < 32 // bitset is 16 bits - int propagateDirectionBitset = (int)(queueValue >>> (COORDINATE_BITS + COORDINATE_BITS + LEVEL_BITS)) & ((1 << 16) - 1); + int propagateDirectionBitset = (int) (queueValue >>> (COORDINATE_BITS + COORDINATE_BITS + LEVEL_BITS)) & ((1 << 16) - 1); if ((queueValue & FLAG_RECHECK_LEVEL) != 0L) { - if (this.getLevel(posX, posZ) != propagatedLevel) { + final int sectionX = posX >> SECTION_SHIFT; + final int sectionZ = posZ >> SECTION_SHIFT; + final Section section = sectionsArray[sectionX + (sectionZ * SECTION_CACHE_WIDTH) + sectionOffset]; + final int localIdx = (posX & (SECTION_SIZE - 1)) | ((posZ & (SECTION_SIZE - 1)) << SECTION_SHIFT); + if ((section.levels[localIdx] & 0xFF) != propagatedLevel) { // not at the level we expect, so something changed. continue; } } else if ((queueValue & FLAG_WRITE_LEVEL) != 0L) { // these are used to restore sources after a propagation decrease - this.setLevel(posX, posZ, propagatedLevel); + final int sectionX = posX >> SECTION_SHIFT; + final int sectionZ = posZ >> SECTION_SHIFT; + final Section section = sectionsArray[sectionX + (sectionZ * SECTION_CACHE_WIDTH) + sectionOffset]; + final int localIdx = (posX & (SECTION_SIZE - 1)) | ((posZ & (SECTION_SIZE - 1)) << SECTION_SHIFT); + final short currentLevel = section.levels[localIdx]; + section.levels[localIdx] = (short) ((currentLevel & ~0xFF) | (propagatedLevel & 0xFF)); + updatedPositions.put(CoordinateUtils.getChunkKey(posX, posZ), (byte) propagatedLevel); } // this bitset represents the values that we have not propagated to @@ -1036,8 +1049,8 @@ public abstract class ThreadedTicketLevelPropagator { // must guarantee that either we propagate everything in 1 radius or we partially propagate for 1 radius // but the rest not propagated are already handled long currentPropagation = ~( - // z = -1 - (1L << ((2 - 1) | ((2 - 1) << 3))) | + // z = -1 + (1L << ((2 - 1) | ((2 - 1) << 3))) | (1L << ((2 + 0) | ((2 - 1) << 3))) | (1L << ((2 + 1) | ((2 - 1) << 3))) | @@ -1095,7 +1108,7 @@ public abstract class ThreadedTicketLevelPropagator { currentPropagation ^= (bitsetLine1 | bitsetLine2 | bitsetLine3); // now try to propagate - final Section section = this.sections[sectionIndex]; + final Section section = sectionsArray[sectionIndex]; // lower 8 bits are current level, next upper 7 bits are source level, next 1 bit is updated source flag final short currentStoredLevel = section.levels[localIndex]; @@ -1106,8 +1119,8 @@ public abstract class ThreadedTicketLevelPropagator { } // update level - section.levels[localIndex] = (short)((currentStoredLevel & ~0xFF) | (toPropagate & 0xFF)); - updatedPositions.putAndMoveToLast(CoordinateUtils.getChunkKey(offX, offZ), (byte)toPropagate); + section.levels[localIndex] = (short) ((currentStoredLevel & ~0xFF) | (toPropagate & 0xFF)); + updatedPositions.putAndMoveToLast(CoordinateUtils.getChunkKey(offX, offZ), (byte) toPropagate); // queue next if (toPropagate > 1) { @@ -1115,7 +1128,7 @@ public abstract class ThreadedTicketLevelPropagator { // the child bitset is 4x4, so we just shift each line by 4 // add the propagation bitset offset to each line to make it easy to OR it into the propagation queue value final long childPropagation = - ((bitsetLine1 >>> (start)) << (COORDINATE_BITS + COORDINATE_BITS + LEVEL_BITS)) | // z = -1 + ((bitsetLine1 >>> (start)) << (COORDINATE_BITS + COORDINATE_BITS + LEVEL_BITS)) | // z = -1 ((bitsetLine2 >>> (start + 8)) << (4 + COORDINATE_BITS + COORDINATE_BITS + LEVEL_BITS)) | // z = 0 ((bitsetLine3 >>> (start + (8 + 8))) << (4 + 4 + COORDINATE_BITS + COORDINATE_BITS + LEVEL_BITS)); // z = 1 @@ -1125,7 +1138,7 @@ public abstract class ThreadedTicketLevelPropagator { queue = this.resizeIncreaseQueue(); } queue[queueLength++] = - ((long)(offX + (offZ << COORDINATE_BITS) + encodeOffset) & ((1L << (COORDINATE_BITS + COORDINATE_BITS)) - 1)) | + ((long) (offX + (offZ << COORDINATE_BITS) + encodeOffset) & ((1L << (COORDINATE_BITS + COORDINATE_BITS)) - 1)) | ((toPropagate & (LEVEL_COUNT - 1L)) << (COORDINATE_BITS + COORDINATE_BITS)) | childPropagation; //(ALL_DIRECTIONS_BITSET << (COORDINATE_BITS + COORDINATE_BITS + LEVEL_BITS)); continue; @@ -1146,18 +1159,19 @@ public abstract class ThreadedTicketLevelPropagator { final int decodeOffsetZ = -this.encodeOffsetZ; final int encodeOffset = this.coordinateOffset; final int sectionOffset = this.sectionIndexOffset; + final Section[] sectionsArray = this.sections; final Long2ByteLinkedOpenHashMap updatedPositions = this.updatedPositions; while (queueReadIndex < queueLength) { final long queueValue = queue[queueReadIndex++]; - final int posX = ((int)queueValue & (COORDINATE_SIZE - 1)) + decodeOffsetX; - final int posZ = (((int)queueValue >>> COORDINATE_BITS) & (COORDINATE_SIZE - 1)) + decodeOffsetZ; - final int propagatedLevel = ((int)queueValue >>> (COORDINATE_BITS + COORDINATE_BITS)) & (LEVEL_COUNT - 1); + final int posX = ((int) queueValue & (COORDINATE_SIZE - 1)) + decodeOffsetX; + final int posZ = (((int) queueValue >>> COORDINATE_BITS) & (COORDINATE_SIZE - 1)) + decodeOffsetZ; + final int propagatedLevel = ((int) queueValue >>> (COORDINATE_BITS + COORDINATE_BITS)) & (LEVEL_COUNT - 1); // note: the above code requires coordinate bits * 2 < 32 // bitset is 16 bits - int propagateDirectionBitset = (int)(queueValue >>> (COORDINATE_BITS + COORDINATE_BITS + LEVEL_BITS)) & ((1 << 16) - 1); + int propagateDirectionBitset = (int) (queueValue >>> (COORDINATE_BITS + COORDINATE_BITS + LEVEL_BITS)) & ((1 << 16) - 1); // this bitset represents the values that we have not propagated to // this bitset lets us determine what directions the neighbours we set should propagate to, in most cases @@ -1172,8 +1186,8 @@ public abstract class ThreadedTicketLevelPropagator { // must guarantee that either we propagate everything in 1 radius or we partially propagate for 1 radius // but the rest not propagated are already handled long currentPropagation = ~( - // z = -1 - (1L << ((2 - 1) | ((2 - 1) << 3))) | + // z = -1 + (1L << ((2 - 1) | ((2 - 1) << 3))) | (1L << ((2 + 0) | ((2 - 1) << 3))) | (1L << ((2 + 1) | ((2 - 1) << 3))) | @@ -1229,7 +1243,7 @@ public abstract class ThreadedTicketLevelPropagator { final long bitsetLine3 = currentPropagation & (7L << (start + (8 + 8))); // now try to propagate - final Section section = this.sections[sectionIndex]; + final Section section = sectionsArray[sectionIndex]; // lower 8 bits are current level, next upper 7 bits are source level, next 1 bit is updated source flag final short currentStoredLevel = section.levels[localIndex]; @@ -1246,7 +1260,7 @@ public abstract class ThreadedTicketLevelPropagator { increaseQueue = this.resizeIncreaseQueue(); } increaseQueue[increaseQueueLength++] = - ((long)(offX + (offZ << COORDINATE_BITS) + encodeOffset) & ((1L << (COORDINATE_BITS + COORDINATE_BITS)) - 1)) | + ((long) (offX + (offZ << COORDINATE_BITS) + encodeOffset) & ((1L << (COORDINATE_BITS + COORDINATE_BITS)) - 1)) | ((currentLevel & (LEVEL_COUNT - 1L)) << (COORDINATE_BITS + COORDINATE_BITS)) | (FLAG_RECHECK_LEVEL | (ALL_DIRECTIONS_BITSET << (COORDINATE_BITS + COORDINATE_BITS + LEVEL_BITS))); continue; @@ -1257,8 +1271,8 @@ public abstract class ThreadedTicketLevelPropagator { //currentPropagation ^= (bitsetLine1 | bitsetLine2 | bitsetLine3); // update level - section.levels[localIndex] = (short)((currentStoredLevel & ~0xFF)); - updatedPositions.putAndMoveToLast(CoordinateUtils.getChunkKey(offX, offZ), (byte)0); + section.levels[localIndex] = (short) ((currentStoredLevel & ~0xFF)); + updatedPositions.putAndMoveToLast(CoordinateUtils.getChunkKey(offX, offZ), (byte) 0); if (sourceLevel != 0) { // re-propagate source @@ -1267,7 +1281,7 @@ public abstract class ThreadedTicketLevelPropagator { increaseQueue = this.resizeIncreaseQueue(); } increaseQueue[increaseQueueLength++] = - ((long)(offX + (offZ << COORDINATE_BITS) + encodeOffset) & ((1L << (COORDINATE_BITS + COORDINATE_BITS)) - 1)) | + ((long) (offX + (offZ << COORDINATE_BITS) + encodeOffset) & ((1L << (COORDINATE_BITS + COORDINATE_BITS)) - 1)) | ((sourceLevel & (LEVEL_COUNT - 1L)) << (COORDINATE_BITS + COORDINATE_BITS)) | (FLAG_WRITE_LEVEL | (ALL_DIRECTIONS_BITSET << (COORDINATE_BITS + COORDINATE_BITS + LEVEL_BITS))); } @@ -1278,7 +1292,7 @@ public abstract class ThreadedTicketLevelPropagator { // the child bitset is 4x4, so we just shift each line by 4 // add the propagation bitset offset to each line to make it easy to OR it into the propagation queue value final long childPropagation = - ((bitsetLine1 >>> (start)) << (COORDINATE_BITS + COORDINATE_BITS + LEVEL_BITS)) | // z = -1 + ((bitsetLine1 >>> (start)) << (COORDINATE_BITS + COORDINATE_BITS + LEVEL_BITS)) | // z = -1 ((bitsetLine2 >>> (start + 8)) << (4 + COORDINATE_BITS + COORDINATE_BITS + LEVEL_BITS)) | // z = 0 ((bitsetLine3 >>> (start + (8 + 8))) << (4 + 4 + COORDINATE_BITS + COORDINATE_BITS + LEVEL_BITS)); // z = 1 @@ -1288,7 +1302,7 @@ public abstract class ThreadedTicketLevelPropagator { queue = this.resizeDecreaseQueue(); } queue[queueLength++] = - ((long)(offX + (offZ << COORDINATE_BITS) + encodeOffset) & ((1L << (COORDINATE_BITS + COORDINATE_BITS)) - 1)) | + ((long) (offX + (offZ << COORDINATE_BITS) + encodeOffset) & ((1L << (COORDINATE_BITS + COORDINATE_BITS)) - 1)) | ((toPropagate & (LEVEL_COUNT - 1L)) << (COORDINATE_BITS + COORDINATE_BITS)) | (ALL_DIRECTIONS_BITSET << (COORDINATE_BITS + COORDINATE_BITS + LEVEL_BITS)); //childPropagation; continue;