Storage Drawers: Forestry Pack

Storage Drawers: Forestry Pack

6M Downloads

Performance of Compacting Drawers findAllMatchingRecipes

metalshark opened this issue · 6 comments

commented

The findAllMatchingRecipes routine can cause server watchdog timeouts, at scale with a high influx of items each tick. Can the results of it for a given CraftingInventory be cached to reduce the work required each time it is called? An example crash:

java.lang.Error: ServerHangWatchdog detected that a single server tick took 60.09 seconds (should be max 0.05)
	at it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap.<init>(Int2IntOpenHashMap.java:101) ~[?:?] {re:classloading}
	at it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap.<init>(Int2IntOpenHashMap.java:122) ~[?:?] {re:classloading}
	at net.minecraft.item.crafting.RecipeItemHelper.<init>(SourceFile:23) ~[?:?] {re:classloading}
	at net.minecraft.item.crafting.ShapelessRecipe.func_77569_a(ShapelessRecipe.java:51) ~[?:?] {re:classloading,pl:accesstransformer:B}
	at net.minecraft.item.crafting.ShapelessRecipe.func_77569_a(ShapelessRecipe.java:15) ~[?:?] {re:classloading,pl:accesstransformer:B}
	at net.minecraft.item.crafting.IRecipeType.func_222148_a(SourceFile:30) ~[?:?] {re:classloading,re:mixin}
	at net.minecraft.item.crafting.RecipeManager.func_215380_a_(RecipeManager.java:94) ~[?:?] {re:mixin,pl:accesstransformer:B,pl:runtimedistcleaner:A,re:classloading,pl:accesstransformer:B,pl:mixin:APP:crumbs.mixins.json:RecipeManagerMixin,pl:mixin:A,pl:runtimedistcleaner:A}
	at net.minecraft.item.crafting.RecipeManager$$Lambda$15318/1364943273.apply(Unknown Source) ~[?:?] {}
	at java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:267) ~[?:1.8.0_201] {}
	at java.util.HashMap$ValueSpliterator.forEachRemaining(HashMap.java:1628) ~[?:1.8.0_201] {}
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) ~[?:1.8.0_201] {}
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[?:1.8.0_201] {}
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) ~[?:1.8.0_201] {}
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[?:1.8.0_201] {}
	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) ~[?:1.8.0_201] {}
	at net.minecraft.item.crafting.RecipeManager.func_215370_b(RecipeManager.java:97) ~[?:?] {re:mixin,pl:accesstransformer:B,pl:runtimedistcleaner:A,re:classloading,pl:accesstransformer:B,pl:mixin:APP:crumbs.mixins.json:RecipeManagerMixin,pl:mixin:A,pl:runtimedistcleaner:A}
	at com.jaquadro.minecraft.storagedrawers.util.CompactingHelper.findAllMatchingRecipes(CompactingHelper.java:171) ~[storagedrawers:1.16.3-8.3.0] {re:classloading}
	at com.jaquadro.minecraft.storagedrawers.util.CompactingHelper.findHigherTier(CompactingHelper.java:79) ~[storagedrawers:1.16.3-8.3.0] {re:classloading}
	at com.jaquadro.minecraft.storagedrawers.block.tile.tiledata.FractionalDrawerGroup$FractionalStorage.populateSlots(FractionalDrawerGroup.java:432) ~[storagedrawers:1.16.3-8.3.0] {re:classloading}
	at com.jaquadro.minecraft.storagedrawers.block.tile.tiledata.FractionalDrawerGroup$FractionalStorage.setStoredItem(FractionalDrawerGroup.java:197) ~[storagedrawers:1.16.3-8.3.0] {re:classloading}
	at com.jaquadro.minecraft.storagedrawers.block.tile.tiledata.FractionalDrawerGroup$FractionalDrawer.setStoredItem(FractionalDrawerGroup.java:596) ~[storagedrawers:1.16.3-8.3.0] {re:classloading}
	at com.jaquadro.minecraft.storagedrawers.capabilities.DrawerItemRepository.insertItem(DrawerItemRepository.java:53) ~[storagedrawers:1.16.3-8.3.0] {re:classloading}
	at com.jaquadro.minecraft.storagedrawers.api.capabilities.IItemRepository.insertItem(IItemRepository.java:43) ~[storagedrawers:1.16.3-8.3.0] {re:classloading}
	at com.jaquadro.minecraft.storagedrawers.capabilities.DrawerItemHandler.insertItemFullScan(DrawerItemHandler.java:89) ~[storagedrawers:1.16.3-8.3.0] {re:classloading}
	at com.jaquadro.minecraft.storagedrawers.capabilities.DrawerItemHandler.insertItem(DrawerItemHandler.java:62) ~[storagedrawers:1.16.3-8.3.0] {re:classloading}
	at com.lothrazar.cyclic.base.TileEntityBase.moveItems(TileEntityBase.java:312) ~[cyclic:1.16.5-1.5.7] {re:classloading}
	at com.lothrazar.cyclic.base.TileEntityBase.moveItems(TileEntityBase.java:286) ~[cyclic:1.16.5-1.5.7] {re:classloading}
	at com.lothrazar.cyclic.block.cable.item.TileCableItem.normalFlow(TileCableItem.java:92) ~[cyclic:1.16.5-1.5.7] {re:classloading}
	at com.lothrazar.cyclic.block.cable.item.TileCableItem.func_73660_a(TileCableItem.java:69) ~[cyclic:1.16.5-1.5.7] {re:classloading}
	at net.minecraft.world.World.func_217391_K(World.java:491) ~[?:?] {re:mixin,pl:accesstransformer:B,pl:runtimedistcleaner:A,re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}
	at net.minecraft.world.server.ServerWorld.func_72835_b(ServerWorld.java:371) ~[?:?] {re:mixin,pl:accesstransformer:B,pl:runtimedistcleaner:A,re:classloading,pl:accesstransformer:B,pl:mixin:APP:mixins.stevekung's_lib.json:server.level.MixinServerLevel,pl:mixin:A,pl:runtimedistcleaner:A}
	at net.minecraft.server.MinecraftServer.func_71190_q(MinecraftServer.java:851) ~[?:?] {re:mixin,pl:accesstransformer:B,pl:runtimedistcleaner:A,re:classloading,pl:accesstransformer:B,pl:mixin:APP:globaldataandresourcepacks.mixins.json:MinecraftServerMixin,pl:mixin:A,pl:runtimedistcleaner:A}
	at net.minecraft.server.dedicated.DedicatedServer.func_71190_q(DedicatedServer.java:291) ~[?:?] {re:classloading,pl:accesstransformer:B}
	at net.minecraft.server.MinecraftServer.func_71217_p(MinecraftServer.java:787) ~[?:?] {re:mixin,pl:accesstransformer:B,pl:runtimedistcleaner:A,re:classloading,pl:accesstransformer:B,pl:mixin:APP:globaldataandresourcepacks.mixins.json:MinecraftServerMixin,pl:mixin:A,pl:runtimedistcleaner:A}
	at net.minecraft.server.MinecraftServer.func_240802_v_(MinecraftServer.java:642) ~[?:?] {re:mixin,pl:accesstransformer:B,pl:runtimedistcleaner:A,re:classloading,pl:accesstransformer:B,pl:mixin:APP:globaldataandresourcepacks.mixins.json:MinecraftServerMixin,pl:mixin:A,pl:runtimedistcleaner:A}
	at net.minecraft.server.MinecraftServer.func_240783_a_(MinecraftServer.java:232) ~[?:?] {re:mixin,pl:accesstransformer:B,pl:runtimedistcleaner:A,re:classloading,pl:accesstransformer:B,pl:mixin:APP:globaldataandresourcepacks.mixins.json:MinecraftServerMixin,pl:mixin:A,pl:runtimedistcleaner:A}
	at net.minecraft.server.MinecraftServer$$Lambda$14313/554322589.run(Unknown Source) ~[?:?] {}
	at java.lang.Thread.run(Thread.java:748) [?:1.8.0_201] {}
commented
commented

How often does this show up? Is the 60 seconds reported from a single call to the method? And how big would you estimate your recipe list is?

commented

Do you know if things were setup in a way that they would empty out and clear, then re-populate? Once it's populated it shouldn't need to call that method again. Should be true even for leaving/joining world.

commented
commented

I've put in a limited solution that I think will solve the majority of the issue, by having the compacting drawers remember what they previously held and what item was originally inserted. This will avoid the expensive population call if they're emptied and re-filled with the same item.

commented

This is now in the latest 1.16