From 401f1ebb3e5ef8acc6ade788f3fa59e29214fd52 Mon Sep 17 00:00:00 2001 From: talchas Date: Mon, 9 Dec 2019 22:39:38 -0800 Subject: [PATCH 1/2] Avoid quadratic behavior from rebuilding the entire crafting cache for each interface visited. Instead rebuild it at most once per tick, like cpu clusters. This is particularly important when channels are disabled, since in that case even adding a cable visits every grid node. --- .../java/appeng/me/cache/CraftingGridCache.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/appeng/me/cache/CraftingGridCache.java b/src/main/java/appeng/me/cache/CraftingGridCache.java index 7bd105ade..1ec8cbc39 100644 --- a/src/main/java/appeng/me/cache/CraftingGridCache.java +++ b/src/main/java/appeng/me/cache/CraftingGridCache.java @@ -114,6 +114,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper private IStorageGrid storageGrid; private IEnergyGrid energyGrid; private boolean updateList = false; + private boolean updatePatterns = false; public CraftingGridCache( final IGrid grid ) { @@ -138,6 +139,12 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper this.updateCPUClusters(); } + if( this.updatePatterns ) + { + this.updatePatterns = false; + this.updatePatterns(); + } + final Iterator craftingLinkIterator = this.craftingLinks.values().iterator(); while( craftingLinkIterator.hasNext() ) { @@ -185,7 +192,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper if( machine instanceof ICraftingProvider ) { this.craftingProviders.remove( machine ); - this.updatePatterns(); + this.updatePatterns = true; } } @@ -219,7 +226,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper if( machine instanceof ICraftingProvider ) { this.craftingProviders.add( (ICraftingProvider) machine ); - this.updatePatterns(); + this.updatePatterns = true; } } @@ -337,7 +344,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper @MENetworkEventSubscribe public void updateCPUClusters( final MENetworkCraftingPatternChange c ) { - this.updatePatterns(); + this.updatePatterns = true; } @Override From 34c490f92bc9e68fcdfe73e1037783c0609f4f97 Mon Sep 17 00:00:00 2001 From: talchas Date: Mon, 9 Dec 2019 22:39:38 -0800 Subject: [PATCH 2/2] Safer implementation of CraftingGridCache updatePatterns coalescing --- src/main/java/appeng/me/Grid.java | 6 ++- src/main/java/appeng/me/GridNode.java | 4 ++ .../appeng/me/cache/CraftingGridCache.java | 41 ++++++++++++++----- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/main/java/appeng/me/Grid.java b/src/main/java/appeng/me/Grid.java index daab0dbd5..4762d4937 100644 --- a/src/main/java/appeng/me/Grid.java +++ b/src/main/java/appeng/me/Grid.java @@ -39,6 +39,7 @@ import appeng.api.util.IReadOnlyCollection; import appeng.core.worlddata.WorldData; import appeng.hooks.TickHandler; import appeng.util.ReadOnlyCollection; +import appeng.me.cache.CraftingGridCache; public class Grid implements IGrid @@ -219,7 +220,10 @@ public class Grid implements IGrid @Override public MENetworkEvent postEvent( final MENetworkEvent ev ) { - return this.eventBus.postEvent( this, ev ); + CraftingGridCache.pauseRebuilds(); + final MENetworkEvent ret = this.eventBus.postEvent( this, ev ); + CraftingGridCache.unpauseRebuilds(); + return ret; } @Override diff --git a/src/main/java/appeng/me/GridNode.java b/src/main/java/appeng/me/GridNode.java index 6dc863a48..958685b8f 100644 --- a/src/main/java/appeng/me/GridNode.java +++ b/src/main/java/appeng/me/GridNode.java @@ -55,6 +55,7 @@ import appeng.api.util.IReadOnlyCollection; import appeng.core.AELog; import appeng.core.worlddata.WorldData; import appeng.hooks.TickHandler; +import appeng.me.cache.CraftingGridCache; import appeng.me.pathfinding.IPathItem; import appeng.util.IWorldCallable; import appeng.util.ReadOnlyCollection; @@ -164,6 +165,8 @@ public class GridNode implements IGridNode, IPathItem { final Object tracker = new Object(); + CraftingGridCache.pauseRebuilds(); + Deque nextRun = new ArrayDeque<>(); nextRun.add( this ); @@ -203,6 +206,7 @@ public class GridNode implements IGridNode, IPathItem } } } + CraftingGridCache.unpauseRebuilds(); } @Override diff --git a/src/main/java/appeng/me/cache/CraftingGridCache.java b/src/main/java/appeng/me/cache/CraftingGridCache.java index 1ec8cbc39..30ecf13b0 100644 --- a/src/main/java/appeng/me/cache/CraftingGridCache.java +++ b/src/main/java/appeng/me/cache/CraftingGridCache.java @@ -114,7 +114,8 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper private IStorageGrid storageGrid; private IEnergyGrid energyGrid; private boolean updateList = false; - private boolean updatePatterns = false; + private static int pauseRebuilds = 0; + private static Set rebuildNeeded = new HashSet<>(); public CraftingGridCache( final IGrid grid ) { @@ -139,12 +140,6 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper this.updateCPUClusters(); } - if( this.updatePatterns ) - { - this.updatePatterns = false; - this.updatePatterns(); - } - final Iterator craftingLinkIterator = this.craftingLinks.values().iterator(); while( craftingLinkIterator.hasNext() ) { @@ -192,7 +187,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper if( machine instanceof ICraftingProvider ) { this.craftingProviders.remove( machine ); - this.updatePatterns = true; + this.updatePatterns(); } } @@ -226,7 +221,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper if( machine instanceof ICraftingProvider ) { this.craftingProviders.add( (ICraftingProvider) machine ); - this.updatePatterns = true; + this.updatePatterns(); } } @@ -247,8 +242,34 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper // nothing! } + public static void pauseRebuilds() + { + pauseRebuilds++; + } + + public static void unpauseRebuilds() + { + pauseRebuilds--; + if (pauseRebuilds == 0 && rebuildNeeded.size() > 0) + { + ImmutableSet needed = ImmutableSet.copyOf(rebuildNeeded); + rebuildNeeded.clear(); + for ( CraftingGridCache cache: needed ) + { + cache.updatePatterns(); + } + } + } + private void updatePatterns() { + // coalesce change events during a grid traversal to a single rebuild + if (pauseRebuilds != 0) + { + rebuildNeeded.add(this); + return; + } + final Map> oldItems = this.craftableItems; // erase list. @@ -344,7 +365,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper @MENetworkEventSubscribe public void updateCPUClusters( final MENetworkCraftingPatternChange c ) { - this.updatePatterns = true; + this.updatePatterns(); } @Override