Improved performance of network scanning

This commit is contained in:
raoulvdberge
2017-05-25 15:07:36 +02:00
parent 8cb37727e5
commit a45529426b
3 changed files with 55 additions and 47 deletions

View File

@@ -1,5 +1,8 @@
# Refined Storage Changelog # Refined Storage Changelog
### 1.4.10
- Improved performance of network scanning (raoulvdberge)
### 1.4.9 ### 1.4.9
- Fixed bug where inventory data was lost sometimes upon opening the world (raoulvdberge) - Fixed bug where inventory data was lost sometimes upon opening the world (raoulvdberge)

View File

@@ -2,7 +2,7 @@ package com.raoulvdberge.refinedstorage.api.network;
import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode; import com.raoulvdberge.refinedstorage.api.network.node.INetworkNode;
import java.util.List; import java.util.Collection;
/** /**
* Represents a graph of all the nodes connected to a network. * Represents a graph of all the nodes connected to a network.
@@ -14,9 +14,9 @@ public interface INetworkNodeGraph {
void rebuild(); void rebuild();
/** /**
* @return a list of all connected nodes * @return a collection of all connected nodes
*/ */
List<INetworkNode> all(); Collection<INetworkNode> all();
/** /**
* Disconnects and notifies all connected nodes. * Disconnects and notifies all connected nodes.

View File

@@ -22,8 +22,8 @@ import static com.raoulvdberge.refinedstorage.proxy.CapabilityNetworkNodeProxy.N
public class NetworkNodeGraph implements INetworkNodeGraph { public class NetworkNodeGraph implements INetworkNodeGraph {
private TileController controller; private TileController controller;
private List<INetworkNode> nodes = new ArrayList<>(); private Set<INetworkNode> nodes = new HashSet<>();
private Set<Integer> nodePositions = new HashSet<>(); private Set<Integer> nodeHashes = new HashSet<>();
public NetworkNodeGraph(TileController controller) { public NetworkNodeGraph(TileController controller) {
this.controller = controller; this.controller = controller;
@@ -39,26 +39,7 @@ public class NetworkNodeGraph implements INetworkNodeGraph {
return; return;
} }
Set<INetworkNode> newNodes = new HashSet<>(); Operator operator = new Operator();
Set<Integer> newNodePositions = new HashSet<>();
Queue<NodeToCheck> toCheck = new ArrayDeque<>();
INetworkNeighborhoodAware.Operator operator = (world, pos, side) -> {
TileEntity tile = world.getTileEntity(pos);
if (tile != null && !tile.isInvalid()) {
if (tile instanceof TileController) {
removeOtherController(world, pos);
} else if (tile.hasCapability(NETWORK_NODE_PROXY_CAPABILITY, side)) {
INetworkNodeProxy otherNodeProxy = NETWORK_NODE_PROXY_CAPABILITY.cast(tile.getCapability(NETWORK_NODE_PROXY_CAPABILITY, side));
INetworkNode otherNode = otherNodeProxy.getNode();
if (newNodes.add(otherNode) && newNodePositions.add(getNodeHash(otherNode))) {
toCheck.add(new NodeToCheck(otherNode, world, pos, side, tile));
}
}
}
};
BlockPos controllerPos = controller.getPos(); BlockPos controllerPos = controller.getPos();
World controllerWorld = controller.getWorld(); World controllerWorld = controller.getWorld();
@@ -69,35 +50,22 @@ public class NetworkNodeGraph implements INetworkNodeGraph {
} }
NodeToCheck currentNodeToCheck; NodeToCheck currentNodeToCheck;
while ((currentNodeToCheck = toCheck.poll()) != null) { while ((currentNodeToCheck = operator.toCheck.poll()) != null) {
currentNodeToCheck.walkNeighborhood(operator); currentNodeToCheck.walkNeighborhood(operator);
} }
List<INetworkNode> oldNodes = nodes;
Set<Integer> oldNodePositions = nodePositions;
nodes = new ArrayList<>(newNodes);
nodePositions = new HashSet<>(newNodePositions);
boolean changed = false;
for (INetworkNode node : nodes) { for (INetworkNode node : nodes) {
if (!oldNodePositions.contains(getNodeHash(node))) { if (operator.uncheckedHashesFromPrevious.contains(getNodeHash(node))) {
node.onConnected(controller); node.onDisconnected(controller);
changed = true; operator.changed = true;
} }
} }
for (INetworkNode oldNode : oldNodes) { this.nodes = operator.newNodes;
if (!nodePositions.contains(getNodeHash(oldNode))) { this.nodeHashes = operator.newNodeHashes;
oldNode.onDisconnected(controller);
changed = true; if (operator.changed) {
}
}
if (changed) {
controller.getDataManager().sendParameterToWatchers(TileController.NODES); controller.getDataManager().sendParameterToWatchers(TileController.NODES);
} }
} }
@@ -109,7 +77,7 @@ public class NetworkNodeGraph implements INetworkNodeGraph {
} }
@Override @Override
public List<INetworkNode> all() { public Collection<INetworkNode> all() {
return nodes; return nodes;
} }
@@ -118,7 +86,7 @@ public class NetworkNodeGraph implements INetworkNodeGraph {
List<INetworkNode> oldNodes = new ArrayList<>(nodes); List<INetworkNode> oldNodes = new ArrayList<>(nodes);
nodes.clear(); nodes.clear();
nodePositions.clear(); nodeHashes.clear();
for (INetworkNode node : oldNodes) { for (INetworkNode node : oldNodes) {
if (node.getNetwork() == controller) { if (node.getNetwork() == controller) {
@@ -151,6 +119,43 @@ public class NetworkNodeGraph implements INetworkNodeGraph {
} }
} }
private class Operator implements INetworkNeighborhoodAware.Operator {
private Set<INetworkNode> newNodes = new HashSet<>();
private Set<Integer> newNodeHashes = new HashSet<>();
private Set<Integer> uncheckedHashesFromPrevious = new HashSet<>(nodeHashes);
private boolean changed;
private Queue<NodeToCheck> toCheck = new ArrayDeque<>();
@Override
public void apply(World world, BlockPos pos, EnumFacing side) {
TileEntity tile = world.getTileEntity(pos);
if (tile != null) {
if (tile instanceof TileController) {
removeOtherController(world, pos);
} else if (tile.hasCapability(NETWORK_NODE_PROXY_CAPABILITY, side)) {
INetworkNodeProxy otherNodeProxy = NETWORK_NODE_PROXY_CAPABILITY.cast(tile.getCapability(NETWORK_NODE_PROXY_CAPABILITY, side));
INetworkNode otherNode = otherNodeProxy.getNode();
int otherNodeHash = getNodeHash(otherNode);
if (newNodes.add(otherNode) && newNodeHashes.add(otherNodeHash)) {
if (!nodeHashes.contains(otherNodeHash)) {
otherNode.onConnected(controller);
changed = true;
}
uncheckedHashesFromPrevious.remove(otherNodeHash);
toCheck.add(new NodeToCheck(otherNode, world, pos, side, tile));
}
}
}
}
}
private class NodeToCheck implements INetworkNeighborhoodAware { private class NodeToCheck implements INetworkNeighborhoodAware {
private final INetworkNode node; private final INetworkNode node;
private final World world; private final World world;