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
### 1.4.10
- Improved performance of network scanning (raoulvdberge)
### 1.4.9
- 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 java.util.List;
import java.util.Collection;
/**
* Represents a graph of all the nodes connected to a network.
@@ -14,9 +14,9 @@ public interface INetworkNodeGraph {
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.

View File

@@ -22,8 +22,8 @@ import static com.raoulvdberge.refinedstorage.proxy.CapabilityNetworkNodeProxy.N
public class NetworkNodeGraph implements INetworkNodeGraph {
private TileController controller;
private List<INetworkNode> nodes = new ArrayList<>();
private Set<Integer> nodePositions = new HashSet<>();
private Set<INetworkNode> nodes = new HashSet<>();
private Set<Integer> nodeHashes = new HashSet<>();
public NetworkNodeGraph(TileController controller) {
this.controller = controller;
@@ -39,26 +39,7 @@ public class NetworkNodeGraph implements INetworkNodeGraph {
return;
}
Set<INetworkNode> newNodes = new HashSet<>();
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));
}
}
}
};
Operator operator = new Operator();
BlockPos controllerPos = controller.getPos();
World controllerWorld = controller.getWorld();
@@ -69,35 +50,22 @@ public class NetworkNodeGraph implements INetworkNodeGraph {
}
NodeToCheck currentNodeToCheck;
while ((currentNodeToCheck = toCheck.poll()) != null) {
while ((currentNodeToCheck = operator.toCheck.poll()) != null) {
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) {
if (!oldNodePositions.contains(getNodeHash(node))) {
node.onConnected(controller);
if (operator.uncheckedHashesFromPrevious.contains(getNodeHash(node))) {
node.onDisconnected(controller);
changed = true;
operator.changed = true;
}
}
for (INetworkNode oldNode : oldNodes) {
if (!nodePositions.contains(getNodeHash(oldNode))) {
oldNode.onDisconnected(controller);
this.nodes = operator.newNodes;
this.nodeHashes = operator.newNodeHashes;
changed = true;
}
}
if (changed) {
if (operator.changed) {
controller.getDataManager().sendParameterToWatchers(TileController.NODES);
}
}
@@ -109,7 +77,7 @@ public class NetworkNodeGraph implements INetworkNodeGraph {
}
@Override
public List<INetworkNode> all() {
public Collection<INetworkNode> all() {
return nodes;
}
@@ -118,7 +86,7 @@ public class NetworkNodeGraph implements INetworkNodeGraph {
List<INetworkNode> oldNodes = new ArrayList<>(nodes);
nodes.clear();
nodePositions.clear();
nodeHashes.clear();
for (INetworkNode node : oldNodes) {
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 final INetworkNode node;
private final World world;