aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/api/threads
diff options
context:
space:
mode:
authorJason Mitchell <mitchej@gmail.com>2024-03-04 02:20:48 -0800
committerGitHub <noreply@github.com>2024-03-04 11:20:48 +0100
commitf3712d3b8dd556087b786a8918904792be231e16 (patch)
treed2d86517c3a8a137398e5fc56892200cbb4931b6 /src/main/java/gregtech/api/threads
parentdc0eb86a4737b73b3bdbf39c6916c19c3aaa8af4 (diff)
downloadGT5-Unofficial-f3712d3b8dd556087b786a8918904792be231e16.tar.gz
GT5-Unofficial-f3712d3b8dd556087b786a8918904792be231e16.tar.bz2
GT5-Unofficial-f3712d3b8dd556087b786a8918904792be231e16.zip
Maybe thread safe (#2523)
* Maybe thread safe * While we're at it, let's reduce allocations by a few orders of magnitude. ~1gb -> 1mb in testing for similar time periods. * use return value of add() again * That's apparently not available on the server side * Spotless apply for branch maybe-thread-safe for #2523 (#2524) spotlessApply --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Diffstat (limited to 'src/main/java/gregtech/api/threads')
-rw-r--r--src/main/java/gregtech/api/threads/GT_Runnable_Cable_Update.java40
-rw-r--r--src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java101
2 files changed, 90 insertions, 51 deletions
diff --git a/src/main/java/gregtech/api/threads/GT_Runnable_Cable_Update.java b/src/main/java/gregtech/api/threads/GT_Runnable_Cable_Update.java
index 31c3c56aa8..4375d21e40 100644
--- a/src/main/java/gregtech/api/threads/GT_Runnable_Cable_Update.java
+++ b/src/main/java/gregtech/api/threads/GT_Runnable_Cable_Update.java
@@ -1,7 +1,6 @@
package gregtech.api.threads;
import net.minecraft.tileentity.TileEntity;
-import net.minecraft.util.ChunkCoordinates;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
@@ -13,29 +12,34 @@ import gregtech.common.GT_Proxy;
public class GT_Runnable_Cable_Update extends GT_Runnable_MachineBlockUpdate {
- protected GT_Runnable_Cable_Update(World aWorld, ChunkCoordinates aCoords) {
- super(aWorld, aCoords);
+ protected GT_Runnable_Cable_Update(World aWorld, int posX, int posY, int posZ) {
+ super(aWorld, posX, posY, posZ);
}
- public static void setCableUpdateValues(World aWorld, ChunkCoordinates aCoords) {
+ public static void setCableUpdateValues(World aWorld, int posX, int posY, int posZ) {
if (isEnabled) {
- EXECUTOR_SERVICE.submit(new GT_Runnable_Cable_Update(aWorld, aCoords));
+ EXECUTOR_SERVICE.submit(new GT_Runnable_Cable_Update(aWorld, posX, posY, posZ));
}
}
@Override
public void run() {
+ int posX, posY, posZ;
try {
while (!tQueue.isEmpty()) {
- final ChunkCoordinates aCoords = tQueue.poll();
+ final long packedCoords = tQueue.dequeueLong();
+ posX = unpackLongX(packedCoords);
+ posY = unpackLongY(packedCoords);
+ posZ = unpackLongZ(packedCoords);
+
final TileEntity tTileEntity;
GT_Proxy.TICK_LOCK.lock();
try {
// we dont want to go over cables that are in unloaded chunks
// keeping the lock just to make sure no CME happens
- if (world.blockExists(aCoords.posX, aCoords.posY, aCoords.posZ)) {
- tTileEntity = world.getTileEntity(aCoords.posX, aCoords.posY, aCoords.posZ);
+ if (world.blockExists(posX, posY, posZ)) {
+ tTileEntity = world.getTileEntity(posX, posY, posZ);
} else {
tTileEntity = null;
}
@@ -51,22 +55,24 @@ public class GT_Runnable_Cable_Update extends GT_Runnable_MachineBlockUpdate {
// only add blocks the cable is connected to
if (tTileEntity instanceof BaseMetaPipeEntity metaPipe
&& metaPipe.getMetaTileEntity() instanceof GT_MetaPipeEntity_Cable cable) {
- ChunkCoordinates tCoords;
- for (final ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) {
+ for (int i = 0; i < ForgeDirection.VALID_DIRECTIONS.length; i++) {
+ final ForgeDirection side = ForgeDirection.VALID_DIRECTIONS[i];
if (cable.isConnectedAtSide(side)) {
- if (visited.add(
- tCoords = new ChunkCoordinates(
- aCoords.posX + side.offsetX,
- aCoords.posY + side.offsetY,
- aCoords.posZ + side.offsetZ)))
- tQueue.add(tCoords);
+ final long tCoords = asLong(posX + side.offsetX, posY + side.offsetY, posZ + side.offsetZ);
+ if (visited.add(tCoords)) {
+ tQueue.enqueue(tCoords);
+ }
}
}
}
}
} catch (Exception e) {
GT_Mod.GT_FML_LOGGER.error(
- "Well this update was broken... " + mCoords
+ "Well this update was broken... " + initialX
+ + ", "
+ + initialY
+ + ", "
+ + initialZ
+ ", mWorld={"
+ world.getProviderName()
+ " @dimId "
diff --git a/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java b/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java
index ceb6adfa7a..3670655eaf 100644
--- a/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java
+++ b/src/main/java/gregtech/api/threads/GT_Runnable_MachineBlockUpdate.java
@@ -1,30 +1,59 @@
package gregtech.api.threads;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Queue;
-import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import net.minecraft.tileentity.TileEntity;
-import net.minecraft.util.ChunkCoordinates;
import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
import gregtech.GT_Mod;
import gregtech.api.GregTech_API;
import gregtech.api.interfaces.tileentity.IMachineBlockUpdateable;
import gregtech.common.GT_Proxy;
+import it.unimi.dsi.fastutil.longs.LongArrayFIFOQueue;
+import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
+import it.unimi.dsi.fastutil.longs.LongSet;
public class GT_Runnable_MachineBlockUpdate implements Runnable {
+ // Borrowed from Angelica until moving to GTNHLib or something
+ final static int SIZE_BITS_X = 26; // 1 + log2(MathHelper.roundUpToPowerOfTwo(30000000), RoundingMode.UNNECESSARY);
+ final static int SIZE_BITS_Z = SIZE_BITS_X;
+ final static int SIZE_BITS_Y = 64 - SIZE_BITS_X - SIZE_BITS_Z;
+ final static long BITS_X = (1L << SIZE_BITS_X) - 1L;
+ final static long BITS_Y = (1L << SIZE_BITS_Y) - 1L;
+ final static long BITS_Z = (1L << SIZE_BITS_Z) - 1L;
+ final static int BIT_SHIFT_Z = SIZE_BITS_Y;
+ final static int BIT_SHIFT_X = SIZE_BITS_Y + SIZE_BITS_Z;
+
+ static long asLong(int x, int y, int z) {
+ long l = 0L;
+ l |= ((long) x & BITS_X) << BIT_SHIFT_X;
+ l |= ((long) y & BITS_Y) << 0;
+ l |= ((long) z & BITS_Z) << BIT_SHIFT_Z;
+ return l;
+ }
+
+ public static int unpackLongX(long packedPos) {
+ return (int) (packedPos << 64 - BIT_SHIFT_X - SIZE_BITS_X >> 64 - SIZE_BITS_X);
+ }
+
+ public static int unpackLongY(long packedPos) {
+ return (int) (packedPos << 64 - SIZE_BITS_Y >> 64 - SIZE_BITS_Y);
+ }
+
+ public static int unpackLongZ(long packedPos) {
+ return (int) (packedPos << 64 - BIT_SHIFT_Z - SIZE_BITS_Z >> 64 - SIZE_BITS_Z);
+ }
+
// used by runner thread
- protected final ChunkCoordinates mCoords;
+ protected final int initialX, initialY, initialZ;
protected final World world;
- protected final Set<ChunkCoordinates> visited = new HashSet<>(80);
- protected final Queue<ChunkCoordinates> tQueue = new LinkedList<>();
+ protected final LongSet visited = new LongOpenHashSet();
+ protected final LongArrayFIFOQueue tQueue = new LongArrayFIFOQueue();
// Threading
private static final ThreadFactory THREAD_FACTORY = r -> {
@@ -35,11 +64,14 @@ public class GT_Runnable_MachineBlockUpdate implements Runnable {
protected static ExecutorService EXECUTOR_SERVICE;
// This class should never be initiated outside of this class!
- protected GT_Runnable_MachineBlockUpdate(World aWorld, ChunkCoordinates aCoords) {
+ protected GT_Runnable_MachineBlockUpdate(World aWorld, int posX, int posY, int posZ) {
this.world = aWorld;
- this.mCoords = aCoords;
- visited.add(aCoords);
- tQueue.add(aCoords);
+ this.initialX = posX;
+ this.initialY = posY;
+ this.initialZ = posZ;
+ final long coords = asLong(posX, posY, posZ);
+ visited.add(coords);
+ tQueue.enqueue(coords);
}
public static boolean isEnabled() {
@@ -69,9 +101,9 @@ public class GT_Runnable_MachineBlockUpdate implements Runnable {
protected static boolean isEnabled = true;
protected static final ThreadLocal<Boolean> perThreadEnable = ThreadLocal.withInitial(() -> true);
- public static void setMachineUpdateValues(World aWorld, ChunkCoordinates aCoords) {
+ public static void setMachineUpdateValues(World aWorld, int posX, int posY, int posZ) {
if (isEnabled() && isCurrentThreadEnabled()) {
- EXECUTOR_SERVICE.submit(new GT_Runnable_MachineBlockUpdate(aWorld, aCoords));
+ EXECUTOR_SERVICE.submit(new GT_Runnable_MachineBlockUpdate(aWorld, posX, posY, posZ));
}
}
@@ -116,9 +148,14 @@ public class GT_Runnable_MachineBlockUpdate implements Runnable {
@Override
public void run() {
+ int posX, posY, posZ;
try {
while (!tQueue.isEmpty()) {
- final ChunkCoordinates aCoords = tQueue.poll();
+ final long packedCoords = tQueue.dequeueLong();
+ posX = unpackLongX(packedCoords);
+ posY = unpackLongY(packedCoords);
+ posZ = unpackLongZ(packedCoords);
+
final TileEntity tTileEntity;
final boolean isMachineBlock;
@@ -128,10 +165,9 @@ public class GT_Runnable_MachineBlockUpdate implements Runnable {
// ConcurrentModificationException. So, lock that shit.
GT_Proxy.TICK_LOCK.lock();
try {
- tTileEntity = world.getTileEntity(aCoords.posX, aCoords.posY, aCoords.posZ);
- isMachineBlock = GregTech_API.isMachineBlock(
- world.getBlock(aCoords.posX, aCoords.posY, aCoords.posZ),
- world.getBlockMetadata(aCoords.posX, aCoords.posY, aCoords.posZ));
+ tTileEntity = world.getTileEntity(posX, posY, posZ);
+ isMachineBlock = GregTech_API
+ .isMachineBlock(world.getBlock(posX, posY, posZ), world.getBlockMetadata(posX, posY, posZ));
} finally {
GT_Proxy.TICK_LOCK.unlock();
}
@@ -148,25 +184,22 @@ public class GT_Runnable_MachineBlockUpdate implements Runnable {
|| (tTileEntity instanceof IMachineBlockUpdateable
&& ((IMachineBlockUpdateable) tTileEntity).isMachineBlockUpdateRecursive())
|| isMachineBlock) {
- ChunkCoordinates tCoords;
-
- if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX + 1, aCoords.posY, aCoords.posZ)))
- tQueue.add(tCoords);
- if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX - 1, aCoords.posY, aCoords.posZ)))
- tQueue.add(tCoords);
- if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY + 1, aCoords.posZ)))
- tQueue.add(tCoords);
- if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY - 1, aCoords.posZ)))
- tQueue.add(tCoords);
- if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY, aCoords.posZ + 1)))
- tQueue.add(tCoords);
- if (visited.add(tCoords = new ChunkCoordinates(aCoords.posX, aCoords.posY, aCoords.posZ - 1)))
- tQueue.add(tCoords);
+ for (int i = 0; i < ForgeDirection.VALID_DIRECTIONS.length; i++) {
+ final ForgeDirection side = ForgeDirection.VALID_DIRECTIONS[i];
+ final long tCoords = asLong(posX + side.offsetX, posY + side.offsetY, posZ + side.offsetZ);
+ if (visited.add(tCoords)) {
+ tQueue.enqueue(tCoords);
+ }
+ }
}
}
} catch (Exception e) {
GT_Mod.GT_FML_LOGGER.error(
- "Well this update was broken... " + mCoords
+ "Well this update was broken... " + initialX
+ + ", "
+ + initialY
+ + ", "
+ + initialZ
+ ", mWorld={"
+ world.getProviderName()
+ " @dimId "