From 30f4cdf5454d8ec52cd4dddade12abebec083a53 Mon Sep 17 00:00:00 2001 From: PrototypeTrousers Date: Tue, 22 Feb 2022 00:02:17 -0300 Subject: [PATCH] attempt at pattern rebuild optimization --- .../java/appeng/helpers/DualityInterface.java | 21 +++- src/main/java/appeng/hooks/TickHandler.java | 17 ++-- src/main/java/appeng/me/Grid.java | 8 +- src/main/java/appeng/me/GridNode.java | 15 ++- .../appeng/me/cache/CraftingGridCache.java | 96 ++++++++++--------- 5 files changed, 82 insertions(+), 75 deletions(-) diff --git a/src/main/java/appeng/helpers/DualityInterface.java b/src/main/java/appeng/helpers/DualityInterface.java index 8413cae3c..90a359102 100644 --- a/src/main/java/appeng/helpers/DualityInterface.java +++ b/src/main/java/appeng/helpers/DualityInterface.java @@ -427,6 +427,8 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn return; } + boolean removed = false; + if( this.craftingList != null ) { final Iterator i = this.craftingList.iterator(); @@ -446,26 +448,36 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn if( !found ) { + removed = true; i.remove(); } } } + boolean newPattern = false; + for( int x = 0; x < accountedFor.length; x++ ) { if( !accountedFor[x] ) { + newPattern = true; this.addToCraftingList( this.patterns.getStackInSlot( x ) ); } } - try { - this.gridProxy.getGrid().postEvent( new MENetworkCraftingPatternChange( this, this.gridProxy.getNode() ) ); + if( removed ) + { + this.gridProxy.getGrid().postEvent( new MENetworkCraftingPatternChange( this, this.gridProxy.getNode() ) ); + } + else if( newPattern ) + { + this.provideCrafting( (ICraftingProviderHelper) this.gridProxy.getCrafting() ); + } } - catch( final GridAccessException e ) + catch( GridAccessException e ) { - // :P + e.printStackTrace(); } } @@ -549,7 +561,6 @@ public class DualityInterface implements IGridTickable, IStorageMonitorable, IIn { try { - this.gridProxy.getGrid().postEvent( new MENetworkCraftingPatternChange( this, this.gridProxy.getNode() ) ); this.gridProxy.getTick().wakeDevice( this.gridProxy.getNode() ); } catch( final GridAccessException e ) diff --git a/src/main/java/appeng/hooks/TickHandler.java b/src/main/java/appeng/hooks/TickHandler.java index bf6af3b0e..6e16de338 100644 --- a/src/main/java/appeng/hooks/TickHandler.java +++ b/src/main/java/appeng/hooks/TickHandler.java @@ -30,6 +30,7 @@ import java.util.Queue; import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import com.google.common.base.Stopwatch; import com.google.common.collect.LinkedListMultimap; @@ -190,10 +191,11 @@ public class TickHandler synchronized ( this.craftingJobs ) { final Collection jobSet = this.craftingJobs.get( wte.world ); - if (!jobSet.isEmpty()) { + if( !jobSet.isEmpty() ) + { final int jobSize = jobSet.size(); final int microSecondsPerTick = AEConfig.instance().getCraftingCalculationTimePerTick() * 1000; - final int simTime = Math.max(1, microSecondsPerTick / jobSize); + final int simTime = Math.max( 1, microSecondsPerTick / jobSize ); jobSet.removeIf( cj -> !cj.simulateFor( simTime ) ); } @@ -206,7 +208,7 @@ public class TickHandler this.tickColors( this.srvPlayerColors ); // ready tiles. final HandlerRep repo = this.getRepo(); - while( !repo.tiles.isEmpty() ) + while ( !repo.tiles.isEmpty() ) { final AEBaseTile bt = repo.tiles.poll(); if( !bt.isInvalid() ) @@ -217,7 +219,8 @@ public class TickHandler // tick networks. this.getRepo().updateNetworks(); - for( final Grid g : this.getRepo().networks ) + List grids = new ArrayList<>( this.getRepo().networks ); + for( final Grid g : grids ) { g.update(); } @@ -238,7 +241,7 @@ public class TickHandler private void tickColors( final HashMap playerSet ) { final Iterator i = playerSet.values().iterator(); - while( i.hasNext() ) + while ( i.hasNext() ) { final PlayerColor pc = i.next(); if( pc.ticksLeft <= 0 ) @@ -259,7 +262,7 @@ public class TickHandler final Stopwatch sw = Stopwatch.createStarted(); IWorldCallable c = null; - while( ( c = queue.poll() ) != null ) + while ( ( c = queue.poll() ) != null ) { try { @@ -283,7 +286,7 @@ public class TickHandler public void registerCraftingSimulation( final World world, final CraftingJob craftingJob ) { - synchronized( this.craftingJobs ) + synchronized ( this.craftingJobs ) { this.craftingJobs.put( world, craftingJob ); } diff --git a/src/main/java/appeng/me/Grid.java b/src/main/java/appeng/me/Grid.java index 4762d4937..6155c884f 100644 --- a/src/main/java/appeng/me/Grid.java +++ b/src/main/java/appeng/me/Grid.java @@ -19,12 +19,8 @@ package appeng.me; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Set; import appeng.api.AEApi; import appeng.api.networking.IGrid; @@ -220,9 +216,7 @@ public class Grid implements IGrid @Override public MENetworkEvent postEvent( final MENetworkEvent ev ) { - CraftingGridCache.pauseRebuilds(); final MENetworkEvent ret = this.eventBus.postEvent( this, ev ); - CraftingGridCache.unpauseRebuilds(); return ret; } diff --git a/src/main/java/appeng/me/GridNode.java b/src/main/java/appeng/me/GridNode.java index 22bf72e02..a2056d5f6 100644 --- a/src/main/java/appeng/me/GridNode.java +++ b/src/main/java/appeng/me/GridNode.java @@ -65,7 +65,7 @@ import net.minecraftforge.common.util.Constants; public class GridNode implements IGridNode, IPathItem { private static final MENetworkChannelsChanged EVENT = new MENetworkChannelsChanged(); - private static final int[] CHANNEL_COUNT = { 0, 8, 32 }; + private static final int[] CHANNEL_COUNT = {0, 8, 32}; private final List connections = new ArrayList<>(); private final IGridBlock gridProxy; @@ -166,8 +166,6 @@ public class GridNode implements IGridNode, IPathItem { final Object tracker = new Object(); - CraftingGridCache.pauseRebuilds(); - Deque nextRun = new ArrayDeque<>(); nextRun.add( this ); @@ -178,9 +176,9 @@ public class GridNode implements IGridNode, IPathItem final Deque nextConn = new ArrayDeque<>(); final IGridConnectionVisitor gcv = (IGridConnectionVisitor) g; - while( !nextRun.isEmpty() ) + while ( !nextRun.isEmpty() ) { - while( !nextConn.isEmpty() ) + while ( !nextConn.isEmpty() ) { gcv.visitConnection( nextConn.poll() ); } @@ -196,7 +194,7 @@ public class GridNode implements IGridNode, IPathItem } else { - while( !nextRun.isEmpty() ) + while ( !nextRun.isEmpty() ) { final Iterable thisRun = nextRun; nextRun = new ArrayDeque<>(); @@ -207,7 +205,6 @@ public class GridNode implements IGridNode, IPathItem } } } - CraftingGridCache.unpauseRebuilds(); } @Override @@ -269,7 +266,7 @@ public class GridNode implements IGridNode, IPathItem @Override public void destroy() { - while( !this.connections.isEmpty() ) + while ( !this.connections.isEmpty() ) { // not part of this network for real anymore. if( this.connections.size() == 1 ) @@ -378,7 +375,7 @@ public class GridNode implements IGridNode, IPathItem @Override public boolean meetsChannelRequirements() { - return( !this.gridProxy.getFlags().contains( GridFlags.REQUIRE_CHANNEL ) || this.getUsedChannels() > 0 ); + return ( !this.gridProxy.getFlags().contains( GridFlags.REQUIRE_CHANNEL ) || this.getUsedChannels() > 0 ); } @Override diff --git a/src/main/java/appeng/me/cache/CraftingGridCache.java b/src/main/java/appeng/me/cache/CraftingGridCache.java index 1f0558dba..8b55c9825 100644 --- a/src/main/java/appeng/me/cache/CraftingGridCache.java +++ b/src/main/java/appeng/me/cache/CraftingGridCache.java @@ -113,9 +113,9 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper private final GenericInterestManager interestManager = new GenericInterestManager<>( this.interests ); private IStorageGrid storageGrid; private IEnergyGrid energyGrid; + int i; private boolean updateList = false; - private static int pauseRebuilds = 0; - private static Set rebuildNeeded = new HashSet<>(); + private boolean updatePatterns = true; public CraftingGridCache( final IGrid grid ) { @@ -140,8 +140,14 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper this.updateCPUClusters(); } + if( updatePatterns ) + { + this.recalculateCraftingPatterns(); + this.updatePatterns = false; + } + final Iterator craftingLinkIterator = this.craftingLinks.values().iterator(); - while( craftingLinkIterator.hasNext() ) + while ( craftingLinkIterator.hasNext() ) { if( craftingLinkIterator.next().isDead( this.grid, this ) ) { @@ -187,7 +193,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper if( machine instanceof ICraftingProvider ) { this.craftingProviders.remove( machine ); - this.updatePatterns(); + this.updatePatterns = true; } } @@ -221,7 +227,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper if( machine instanceof ICraftingProvider ) { this.craftingProviders.add( (ICraftingProvider) machine ); - this.updatePatterns(); + this.updatePatterns = true; } } @@ -242,36 +248,15 @@ 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; - } + this.updatePatterns = true; + } - final Object2ObjectMap> oldItems = new Object2ObjectOpenHashMap<>(this.craftableItems); - final Set oldEmitableItems = new HashSet<>(this.emitableItems); + private void recalculateCraftingPatterns() + { + final Object2ObjectMap> oldItems = new Object2ObjectOpenHashMap<>( this.craftableItems ); + final Set oldEmitableItems = new HashSet<>( this.emitableItems ); // erase list. this.craftingMethods.clear(); @@ -312,25 +297,29 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper this.craftableItems.put( e.getKey(), ImmutableList.copyOf( e.getValue() ) ); } - Object2ObjectMap> craftablesChanged = new Object2ObjectArrayMap<>(); + List craftablesChanged = new ArrayList<>(); ObjectSet>> i = oldItems.entrySet(); - for ( Entry> ais : i) { - if (!this.craftableItems.containsKey( ais.getKey() )) { + for( Entry> ais : i ) + { + if( !this.craftableItems.containsKey( ais.getKey() ) ) + { IAEItemStack changedStack = ais.getKey().copy(); changedStack.reset(); changedStack.setCraftable( false ); - craftablesChanged.put( changedStack, ais.getValue() ); + craftablesChanged.add( changedStack ); } } ObjectSet>> j = this.craftableItems.entrySet(); - for ( Entry> ais : j) { - if (!oldItems.containsKey( ais )){ + for( Entry> ais : j ) + { + if( !oldItems.containsKey( ais ) ) + { IAEItemStack changedStack = ais.getKey().copy(); changedStack.reset(); changedStack.setCraftable( true ); - craftablesChanged.put( changedStack, ais.getValue() ); + craftablesChanged.add( changedStack ); } } @@ -341,7 +330,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper IAEItemStack changedStack = st.copy(); changedStack.reset(); changedStack.setCraftable( false ); - craftablesChanged.put( changedStack, null ); + craftablesChanged.add( changedStack ); } } @@ -352,12 +341,11 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper IAEItemStack changedStack = st.copy(); changedStack.reset(); changedStack.setCraftable( true ); - craftablesChanged.put( changedStack, null ); + craftablesChanged.add( changedStack ); } } - this.storageGrid.postCraftablesChanges( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ), craftablesChanged.keySet(), - new BaseActionSource() ); + this.storageGrid.postCraftablesChanges( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ), craftablesChanged, new BaseActionSource() ); } private void updateCPUClusters() @@ -423,6 +411,21 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper { details.add( medium ); } + + if( !updatePatterns ) + { + List newCraftables = new ArrayList<>(); + for( IAEItemStack stack : api.getOutputs() ) + { + ImmutableList a = this.craftableItems.get( stack ); + if( a == null || a.get( 0 ).getPriority() < api.getPriority() ) + { + this.craftableItems.put( stack, ImmutableList.of( api ) ); + newCraftables.add( stack.copy().reset().setCraftable( true ) ); + } + } + this.storageGrid.postCraftablesChanges( AEApi.instance().storage().getStorageChannel( IItemStorageChannel.class ), newCraftables, new BaseActionSource() ); + } } @Override @@ -596,8 +599,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper } } - Collections.sort( validCpusClusters, ( firstCluster, nextCluster ) -> - { + Collections.sort( validCpusClusters, ( firstCluster, nextCluster ) -> { if( prioritizePower ) { final int comparison1 = Long.compare( nextCluster.getCoProcessors(), firstCluster.getCoProcessors() ); @@ -676,7 +678,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper public boolean hasCpu( final ICraftingCPU cpu ) { - if (cpu instanceof CraftingCPUCluster) + if( cpu instanceof CraftingCPUCluster ) { return this.craftingCPUClusters.contains( (CraftingCPUCluster) cpu ); } @@ -710,7 +712,7 @@ public class CraftingGridCache implements ICraftingGrid, ICraftingProviderHelper private void findNext() { - while( this.iterator.hasNext() && this.cpuCluster == null ) + while ( this.iterator.hasNext() && this.cpuCluster == null ) { this.cpuCluster = this.iterator.next(); if( !this.cpuCluster.isActive() || this.cpuCluster.isDestroyed() )