death by one million hashmap lookups (68ms -> 8ms over 60 seconds)

This commit is contained in:
George Paton 2025-02-28 11:56:03 +11:00
parent 9da32595ff
commit dc70967279
7 changed files with 52 additions and 41 deletions

View File

@ -17,11 +17,6 @@ public class NeutronNodeWorld {
return streamWorld != null ? streamWorld.nodeCache.get(pos) : null;
}
public static void addNode(World world, NeutronNode node) {
StreamWorld streamWorld = getOrAddWorld(world);
streamWorld.nodeCache.put(node.pos, node);
}
public static void removeNode(World world, BlockPos pos) {
StreamWorld streamWorld = streamWorlds.get(world);
if(streamWorld == null) return;
@ -58,7 +53,7 @@ public class NeutronNodeWorld {
public void runStreamInteractions(World world) {
for(NeutronStream stream : streams) {
stream.runStreamInteraction(world);
stream.runStreamInteraction(world, this);
}
}
@ -75,7 +70,7 @@ public class NeutronNodeWorld {
for(NeutronNode cachedNode : nodeCache.values()) {
if(cachedNode.type == NeutronStream.NeutronType.RBMK) {
RBMKNeutronHandler.RBMKNeutronNode node = (RBMKNeutronHandler.RBMKNeutronNode) cachedNode;
toRemove.addAll(node.checkNode());
toRemove.addAll(node.checkNode(this));
}
/* TODO: actually do this and uncache pile nodes
if(cachedNode.type == NeutronStream.NeutronType.PILE) {
@ -90,6 +85,14 @@ public class NeutronNodeWorld {
}
}
public NeutronNode getNode(BlockPos pos) {
return nodeCache.get(pos);
}
public void addNode(NeutronNode node) {
nodeCache.put(node.pos, node);
}
public void removeNode(BlockPos pos) {
nodeCache.remove(pos);
}

View File

@ -1,5 +1,6 @@
package com.hbm.handler.neutron;
import com.hbm.handler.neutron.NeutronNodeWorld.StreamWorld;
import com.hbm.util.fauxpointtwelve.BlockPos;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
@ -72,5 +73,5 @@ public abstract class NeutronStream {
};
}
public abstract void runStreamInteraction(World worldObj);
public abstract void runStreamInteraction(World worldObj, StreamWorld streamWorld);
}

View File

@ -2,6 +2,7 @@ package com.hbm.handler.neutron;
import api.hbm.block.IPileNeutronReceiver;
import com.hbm.blocks.ModBlocks;
import com.hbm.handler.neutron.NeutronNodeWorld.StreamWorld;
import com.hbm.tileentity.machine.pile.TileEntityPileBase;
import com.hbm.util.ContaminationUtil;
import com.hbm.util.fauxpointtwelve.BlockPos;
@ -26,9 +27,9 @@ public class PileNeutronHandler {
}
public static PileNeutronNode makeNode(TileEntityPileBase tile) {
public static PileNeutronNode makeNode(StreamWorld streamWorld, TileEntityPileBase tile) {
BlockPos pos = new BlockPos(tile);
PileNeutronNode node = (PileNeutronNode) NeutronNodeWorld.getNode(tile.getWorldObj(), pos);
PileNeutronNode node = (PileNeutronNode) streamWorld.getNode(pos);
return node != null ? node : new PileNeutronNode(tile);
}
@ -44,7 +45,7 @@ public class PileNeutronHandler {
@SuppressWarnings("unchecked")
@Override
public void runStreamInteraction(World worldObj) {
public void runStreamInteraction(World worldObj, StreamWorld streamWorld) {
TileEntityPileBase originTE = (TileEntityPileBase) origin.tile;
BlockPos pos = new BlockPos(originTE);
@ -64,7 +65,7 @@ public class PileNeutronHandler {
TileEntity tile;
NeutronNode node = NeutronNodeWorld.getNode(worldObj, nodePos);
NeutronNode node = streamWorld.getNode(nodePos);
if(node != null && node instanceof PileNeutronNode) {
tile = node.tile;
} else {
@ -72,7 +73,7 @@ public class PileNeutronHandler {
if(tile == null) return;
if(tile instanceof TileEntityPileBase) {
NeutronNodeWorld.addNode(worldObj, new PileNeutronNode((TileEntityPileBase) tile));
streamWorld.addNode(new PileNeutronNode((TileEntityPileBase) tile));
}
}

View File

@ -1,6 +1,7 @@
package com.hbm.handler.neutron;
import com.hbm.blocks.machine.rbmk.RBMKBase;
import com.hbm.handler.neutron.NeutronNodeWorld.StreamWorld;
import com.hbm.handler.radiation.ChunkRadiationManager;
import com.hbm.tileentity.machine.rbmk.*;
import com.hbm.util.fauxpointtwelve.BlockPos;
@ -37,9 +38,9 @@ public class RBMKNeutronHandler {
return worldObj.getTileEntity(pos.getX(), pos.getY(), pos.getZ());
}
public static RBMKNeutronNode makeNode(TileEntityRBMKBase tile) {
public static RBMKNeutronNode makeNode(StreamWorld streamWorld, TileEntityRBMKBase tile) {
BlockPos pos = new BlockPos(tile);
RBMKNeutronNode node = (RBMKNeutronNode) NeutronNodeWorld.getNode(tile.getWorldObj(), pos);
RBMKNeutronNode node = (RBMKNeutronNode) streamWorld.getNode(pos);
return node != null ? node : new RBMKNeutronNode(tile, tile.getRBMKType(), tile.hasLid());
}
@ -97,11 +98,10 @@ public class RBMKNeutronHandler {
};
}
public List<BlockPos> checkNode() {
public List<BlockPos> checkNode(StreamWorld streamWorld) {
List<BlockPos> list = new ArrayList<>();
BlockPos pos = new BlockPos(this.tile);
World world = tile.getWorldObj();
RBMKNeutronStream[] streams = new RBMKNeutronStream[TileEntityRBMKRod.fluxDirs.length];
@ -117,7 +117,7 @@ public class RBMKNeutronHandler {
if(!rod.hasRod || rod.lastFluxQuantity == 0) {
for(RBMKNeutronStream stream : streams) {
for(NeutronNode node : stream.getNodes(false))
for(NeutronNode node : stream.getNodes(streamWorld, false))
if(node != null)
list.add(new BlockPos(node.tile));
}
@ -155,7 +155,7 @@ public class RBMKNeutronHandler {
if(nodePos == null)
continue;
NeutronNode node = NeutronNodeWorld.getNode(world, nodePos);
NeutronNode node = streamWorld.getNode(nodePos);
if(node != null && node.tile instanceof TileEntityRBMKRod) {
@ -177,7 +177,7 @@ public class RBMKNeutronHandler {
// Check if non-rod nodes should be uncached due to no rod in range.
for(RBMKNeutronStream stream : streams) {
NeutronNode[] nodes = stream.getNodes(false);
NeutronNode[] nodes = stream.getNodes(streamWorld, false);
for(NeutronNode node : nodes) {
if(!(node == null) && node.tile instanceof TileEntityRBMKRod)
@ -209,7 +209,7 @@ public class RBMKNeutronHandler {
// Does NOT include the origin node
// USES THE CACHE!!!
public NeutronNode[] getNodes(boolean addNode) {
public NeutronNode[] getNodes(StreamWorld streamWorld, boolean addNode) {
NeutronNode[] positions = new RBMKNeutronNode[fluxRange];
BlockPos pos = new BlockPos(origin.tile);
@ -221,16 +221,16 @@ public class RBMKNeutronHandler {
pos.mutate(origin.tile.xCoord + x, origin.tile.yCoord, origin.tile.zCoord + z);
NeutronNode node = NeutronNodeWorld.getNode(world, pos);
NeutronNode node = streamWorld.getNode(pos);
if(node != null && node instanceof RBMKNeutronNode) {
positions[i - 1] = node;
} else if(this.origin.tile.getBlockType() instanceof RBMKBase) {
TileEntity te = blockPosToTE(world, pos);
if(te instanceof TileEntityRBMKBase) {
TileEntityRBMKBase rbmkBase = (TileEntityRBMKBase) te;
node = makeNode(rbmkBase);
node = makeNode(streamWorld, rbmkBase);
positions[i - 1] = node;
if(addNode) NeutronNodeWorld.addNode(world, node);
if(addNode) streamWorld.addNode(node);
}
}
}
@ -238,7 +238,7 @@ public class RBMKNeutronHandler {
}
// The... small one? whatever it's still pretty big, runs the interaction for the stream.
public void runStreamInteraction(World worldObj) {
public void runStreamInteraction(World worldObj, StreamWorld streamWorld) {
// do nothing if there's nothing to do lmao
if(fluxQuantity == 0D)
@ -248,14 +248,14 @@ public class RBMKNeutronHandler {
TileEntityRBMKBase originTE;
NeutronNode node = NeutronNodeWorld.getNode(worldObj, pos);
NeutronNode node = streamWorld.getNode(pos);
if(node != null) {
originTE = (TileEntityRBMKBase) node.tile;
} else {
originTE = (TileEntityRBMKBase) blockPosToTE(worldObj, pos);
if(originTE == null) return; // Doesn't exist anymore!
NeutronNodeWorld.addNode(worldObj, new RBMKNeutronNode(originTE, originTE.getRBMKType(), originTE.hasLid()));
streamWorld.addNode(new RBMKNeutronNode(originTE, originTE.getRBMKType(), originTE.hasLid()));
}
int moderatedCount = 0;
@ -269,12 +269,12 @@ public class RBMKNeutronHandler {
if(fluxQuantity == 0D) // Whoops, used it all up!
return;
NeutronNode targetNode = NeutronNodeWorld.getNode(worldObj, targetPos);
NeutronNode targetNode = streamWorld.getNode(targetPos);
if(targetNode == null) {
TileEntity te = blockPosToTE(worldObj, targetPos); // ok, maybe it didn't get added to the list somehow??
if(te instanceof TileEntityRBMKBase) {
targetNode = makeNode((TileEntityRBMKBase) te);
NeutronNodeWorld.addNode(worldObj, targetNode); // whoops!
targetNode = makeNode(streamWorld, (TileEntityRBMKBase) te);
streamWorld.addNode(targetNode); // whoops!
} else {
int hits = getHits(targetPos); // Get the amount of hits on blocks.
if(hits == columnHeight) // If stream is fully blocked.
@ -360,7 +360,7 @@ public class RBMKNeutronHandler {
}
}
NeutronNode[] nodes = getNodes(true);
NeutronNode[] nodes = getNodes(streamWorld, true);
NeutronNode lastNode = nodes[(nodes.length - 1)];

View File

@ -1,6 +1,7 @@
package com.hbm.tileentity.machine.pile;
import com.hbm.handler.neutron.NeutronNodeWorld;
import com.hbm.handler.neutron.NeutronNodeWorld.StreamWorld;
import com.hbm.handler.neutron.PileNeutronHandler;
import com.hbm.handler.neutron.PileNeutronHandler.PileNeutronStream;
import com.hbm.handler.neutron.PileNeutronHandler.PileNeutronNode;
@ -36,11 +37,12 @@ public abstract class TileEntityPileBase extends TileEntity {
return;
}
PileNeutronNode node = (PileNeutronNode) NeutronNodeWorld.getNode(worldObj, pos);
StreamWorld streamWorld = NeutronNodeWorld.getOrAddWorld(worldObj);
PileNeutronNode node = (PileNeutronNode) streamWorld.getNode(pos);
if(node == null) {
node = PileNeutronHandler.makeNode(this);
NeutronNodeWorld.addNode(worldObj, node);
node = PileNeutronHandler.makeNode(streamWorld, this);
streamWorld.addNode(node);
}
Vec3 neutronVector = Vec3.createVectorHelper(1, 0, 0);

View File

@ -6,6 +6,7 @@ import com.hbm.blocks.machine.rbmk.RBMKRod;
import com.hbm.entity.projectile.EntityRBMKDebris.DebrisType;
import com.hbm.handler.CompatHandler;
import com.hbm.handler.neutron.NeutronNodeWorld;
import com.hbm.handler.neutron.NeutronNodeWorld.StreamWorld;
import com.hbm.handler.neutron.RBMKNeutronHandler;
import com.hbm.handler.radiation.ChunkRadiationManager;
import com.hbm.handler.neutron.RBMKNeutronHandler.RBMKNeutronNode;
@ -203,11 +204,12 @@ public class TileEntityRBMKRod extends TileEntityRBMKSlottedBase implements IRBM
return;
}
RBMKNeutronNode node = (RBMKNeutronNode) NeutronNodeWorld.getNode(worldObj, pos);
StreamWorld streamWorld = NeutronNodeWorld.getOrAddWorld(worldObj);
RBMKNeutronNode node = (RBMKNeutronNode) streamWorld.getNode(pos);
if(node == null) {
node = RBMKNeutronHandler.makeNode(this);
NeutronNodeWorld.addNode(worldObj, node);
node = RBMKNeutronHandler.makeNode(streamWorld, this);
streamWorld.addNode(node);
}
for(ForgeDirection dir : fluxDirs) {

View File

@ -2,6 +2,7 @@ package com.hbm.tileentity.machine.rbmk;
import com.hbm.handler.neutron.NeutronNodeWorld;
import com.hbm.handler.neutron.RBMKNeutronHandler;
import com.hbm.handler.neutron.NeutronNodeWorld.StreamWorld;
import com.hbm.tileentity.machine.rbmk.TileEntityRBMKConsole.ColumnType;
import com.hbm.util.fauxpointtwelve.BlockPos;
@ -34,11 +35,12 @@ public class TileEntityRBMKRodReaSim extends TileEntityRBMKRod {
return;
}
RBMKNeutronNode node = (RBMKNeutronNode) NeutronNodeWorld.getNode(worldObj, pos);
StreamWorld streamWorld = NeutronNodeWorld.getOrAddWorld(worldObj);
RBMKNeutronNode node = (RBMKNeutronNode) streamWorld.getNode(pos);
if(node == null) {
node = makeNode(this);
NeutronNodeWorld.addNode(worldObj, node);
node = makeNode(streamWorld, this);
streamWorld.addNode(node);
}
int count = RBMKDials.getReaSimCount(worldObj);
@ -48,7 +50,7 @@ public class TileEntityRBMKRodReaSim extends TileEntityRBMKRod {
neutronVector.rotateAroundY((float)(Math.PI * 2D * worldObj.rand.nextDouble()));
new RBMKNeutronHandler.RBMKNeutronStream(makeNode(this), neutronVector, flux, ratio);
new RBMKNeutronHandler.RBMKNeutronStream(makeNode(streamWorld, this), neutronVector, flux, ratio);
// Create new neutron streams
}
}