From b077b53132e2be1c4058aa5af806f0957ae02625 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 4 May 2023 19:53:39 -0400 Subject: [PATCH 1/6] Bump maximum models in memory from 1k to 10k --- .../dynamicresources/ModelBakeryHelpers.java | 13 +++++++++++++ .../perf/dynamic_resources/ModelBakeryMixin.java | 8 ++++---- .../perf/dynamic_resources/ModelBakeryMixin.java | 8 ++++---- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelBakeryHelpers.java b/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelBakeryHelpers.java index a1b20bc1..9d461add 100644 --- a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelBakeryHelpers.java +++ b/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelBakeryHelpers.java @@ -39,6 +39,19 @@ import static net.minecraft.client.resources.model.ModelBakery.BLOCK_ENTITY_MARK import static net.minecraft.client.resources.model.ModelBakery.GENERATION_MARKER; public class ModelBakeryHelpers { + /** + * The maximum number of baked models kept in memory at once. + */ + public static final int MAX_BAKED_MODEL_COUNT = 10000; + /** + * The maximum number of unbaked models kept in memory at once. + */ + public static final int MAX_UNBAKED_MODEL_COUNT = 10000; + /** + * The time in seconds after which a model becomes eligible for eviction if not used. + */ + public static final int MAX_MODEL_LIFETIME_SECS = 90; + private static void gatherAdditionalViaManualScan(List untrustedPacks, Set knownLocations, Collection uncertainLocations, String filePrefix) { if(untrustedPacks.size() > 0) { diff --git a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakeryMixin.java b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakeryMixin.java index 83a50d35..185bb732 100644 --- a/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakeryMixin.java +++ b/fabric/src/main/java/org/embeddedt/modernfix/fabric/mixin/perf/dynamic_resources/ModelBakeryMixin.java @@ -86,15 +86,15 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { private void replaceTopLevelBakedModels(ProfilerFiller filler, String s) { this.inTextureGatheringPass = true; this.loadedBakedModels = CacheBuilder.newBuilder() - .expireAfterAccess(3, TimeUnit.MINUTES) - .maximumSize(1000) + .expireAfterAccess(ModelBakeryHelpers.MAX_MODEL_LIFETIME_SECS, TimeUnit.SECONDS) + .maximumSize(ModelBakeryHelpers.MAX_BAKED_MODEL_COUNT) .concurrencyLevel(8) .removalListener(this::onModelRemoved) .softValues() .build(); this.loadedModels = CacheBuilder.newBuilder() - .expireAfterAccess(3, TimeUnit.MINUTES) - .maximumSize(1000) + .expireAfterAccess(ModelBakeryHelpers.MAX_MODEL_LIFETIME_SECS, TimeUnit.SECONDS) + .maximumSize(ModelBakeryHelpers.MAX_UNBAKED_MODEL_COUNT) .concurrencyLevel(8) .removalListener(this::onModelRemoved) .softValues() diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakeryMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakeryMixin.java index fbc8730d..a71b7ed7 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakeryMixin.java +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/dynamic_resources/ModelBakeryMixin.java @@ -99,15 +99,15 @@ public abstract class ModelBakeryMixin implements IExtendedModelBakery { @Inject(method = "(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/client/color/block/BlockColors;Z)V", at = @At("RETURN")) private void replaceTopLevelBakedModels(ResourceManager manager, BlockColors colors, boolean vanillaBakery, CallbackInfo ci) { this.loadedBakedModels = CacheBuilder.newBuilder() - .expireAfterAccess(3, TimeUnit.MINUTES) - .maximumSize(1000) + .expireAfterAccess(ModelBakeryHelpers.MAX_MODEL_LIFETIME_SECS, TimeUnit.SECONDS) + .maximumSize(ModelBakeryHelpers.MAX_BAKED_MODEL_COUNT) .concurrencyLevel(8) .removalListener(this::onModelRemoved) .softValues() .build(); this.loadedModels = CacheBuilder.newBuilder() - .expireAfterAccess(3, TimeUnit.MINUTES) - .maximumSize(1000) + .expireAfterAccess(ModelBakeryHelpers.MAX_MODEL_LIFETIME_SECS, TimeUnit.SECONDS) + .maximumSize(ModelBakeryHelpers.MAX_UNBAKED_MODEL_COUNT) .concurrencyLevel(8) .removalListener(this::onModelRemoved) .softValues() From 8d7b351d531098c6fce07b840684530092fc9044 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 4 May 2023 19:55:57 -0400 Subject: [PATCH 2/6] Increase eviction time --- .../modernfix/dynamicresources/ModelBakeryHelpers.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelBakeryHelpers.java b/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelBakeryHelpers.java index 9d461add..12ef8d8b 100644 --- a/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelBakeryHelpers.java +++ b/common/src/main/java/org/embeddedt/modernfix/dynamicresources/ModelBakeryHelpers.java @@ -50,7 +50,7 @@ public class ModelBakeryHelpers { /** * The time in seconds after which a model becomes eligible for eviction if not used. */ - public static final int MAX_MODEL_LIFETIME_SECS = 90; + public static final int MAX_MODEL_LIFETIME_SECS = 300; private static void gatherAdditionalViaManualScan(List untrustedPacks, Set knownLocations, Collection uncertainLocations, String filePrefix) { From 77e21751239f7adcd8408d2367ca9f2492f69e79 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Thu, 4 May 2023 21:54:57 -0400 Subject: [PATCH 3/6] Fix material cache on Fabric Fixes #72 --- .../mixin/perf/cache_model_materials/VanillaModelMixin.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/cache_model_materials/VanillaModelMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/cache_model_materials/VanillaModelMixin.java index 96c455fe..5b8fe094 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/cache_model_materials/VanillaModelMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/cache_model_materials/VanillaModelMixin.java @@ -4,8 +4,6 @@ import com.mojang.datafixers.util.Pair; import net.minecraft.client.renderer.block.model.BlockModel; import net.minecraft.client.resources.model.UnbakedModel; import net.minecraft.client.resources.model.Material; -import net.minecraft.client.renderer.block.model.MultiVariant; -import net.minecraft.client.renderer.block.model.multipart.MultiPart; import net.minecraft.resources.ResourceLocation; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.duck.ICachedMaterialsModel; @@ -19,7 +17,8 @@ import java.util.Collections; import java.util.Set; import java.util.function.Function; -@Mixin(value = {MultiVariant.class, MultiPart.class, BlockModel.class}) +/* only cache BlockModel to prevent issues with CTM on Fabric */ +@Mixin(value = {BlockModel.class}) @ClientOnlyMixin public class VanillaModelMixin implements ICachedMaterialsModel { private Collection materialsCache = null; From 2cdc8b88a5d0c234cb0f3f2593da947f7c44fdcc Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Fri, 5 May 2023 09:38:36 -0400 Subject: [PATCH 4/6] Make block model cache overridable for even more invasive mods --- .../BlockModelShaperMixin.java | 4 +- .../modernfix/util/DynamicOverridableMap.java | 42 +++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 common/src/main/java/org/embeddedt/modernfix/util/DynamicOverridableMap.java diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockModelShaperMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockModelShaperMixin.java index 129157b6..c5c70db9 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockModelShaperMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/dynamic_resources/BlockModelShaperMixin.java @@ -6,7 +6,7 @@ import net.minecraft.client.resources.model.ModelManager; import net.minecraft.world.level.block.state.BlockState; import org.embeddedt.modernfix.annotation.ClientOnlyMixin; import org.embeddedt.modernfix.dynamicresources.ModelLocationCache; -import org.embeddedt.modernfix.util.DynamicMap; +import org.embeddedt.modernfix.util.DynamicOverridableMap; import org.spongepowered.asm.mixin.*; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -26,7 +26,7 @@ public class BlockModelShaperMixin { @Inject(method = "", at = @At("RETURN")) private void replaceModelMap(CallbackInfo ci) { // replace the backing map for mods which will access it - this.modelByStateCache = new DynamicMap<>(state -> modelManager.getModel(ModelLocationCache.get(state))); + this.modelByStateCache = new DynamicOverridableMap<>(state -> modelManager.getModel(ModelLocationCache.get(state))); } /** diff --git a/common/src/main/java/org/embeddedt/modernfix/util/DynamicOverridableMap.java b/common/src/main/java/org/embeddedt/modernfix/util/DynamicOverridableMap.java new file mode 100644 index 00000000..e16d3f96 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/util/DynamicOverridableMap.java @@ -0,0 +1,42 @@ +package org.embeddedt.modernfix.util; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.function.Function; + +public class DynamicOverridableMap extends DynamicMap { + private final Map overrideMap; + + public DynamicOverridableMap(Function function) { + super(function); + overrideMap = new Object2ObjectOpenHashMap<>(); + } + + @Override + public @Nullable V put(K k, V v) { + if(v == null) + throw new IllegalArgumentException(); + overrideMap.put(k, v); + return null; + } + + @Override + public V get(Object o) { + V val = overrideMap.get(o); + if(val != null) + return val; + return super.get(o); + } + + @Override + public void putAll(@NotNull Map map) { + for(V val : map.values()) { + if(val == null) + throw new IllegalArgumentException(); + } + overrideMap.putAll(map); + } +} From 3f82c7459a255fa74a075cb41a41d45d04cef1f9 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Fri, 5 May 2023 09:46:49 -0400 Subject: [PATCH 5/6] Fix crash with Charm --- .../org/embeddedt/modernfix/entity/EntityRendererMap.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/entity/EntityRendererMap.java b/common/src/main/java/org/embeddedt/modernfix/entity/EntityRendererMap.java index df280415..1f25f533 100644 --- a/common/src/main/java/org/embeddedt/modernfix/entity/EntityRendererMap.java +++ b/common/src/main/java/org/embeddedt/modernfix/entity/EntityRendererMap.java @@ -75,7 +75,9 @@ public class EntityRendererMap implements Map, EntityRenderer> if(renderer == null) throw new AssertionError("Returned entity renderer should never be null"); return renderer; - } catch(ExecutionException e) { + } catch (IllegalStateException e) { + return null; /* emulate value not being present if recursive load occurs */ + } catch (ExecutionException e) { throw new RuntimeException(e); } } From cc36e0c3f1395b6d94b0ffa9d8b63c1087302aa2 Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Fri, 5 May 2023 10:45:59 -0400 Subject: [PATCH 6/6] Ensure Lithium's cache fields get generated Fixes #74 --- .../BlockStateBaseMixin.java | 39 +++++++++++++++---- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockStateBaseMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockStateBaseMixin.java index 76d9fadf..5daa0af2 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockStateBaseMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/reduce_blockstate_cache_rebuilds/BlockStateBaseMixin.java @@ -3,10 +3,13 @@ package org.embeddedt.modernfix.common.mixin.perf.reduce_blockstate_cache_rebuil import net.minecraft.world.level.block.state.BlockBehaviour; import org.embeddedt.modernfix.duck.IBlockState; import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Dynamic; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(BlockBehaviour.BlockStateBase.class) @@ -23,13 +26,7 @@ public abstract class BlockStateBaseMixin implements IBlockState { cacheInvalid = true; } - @Redirect(method = "*", at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;cache:Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase$Cache;", - ordinal = 0 - )) - private BlockBehaviour.BlockStateBase.Cache initCacheIfNeeded(BlockBehaviour.BlockStateBase base) { + private BlockBehaviour.BlockStateBase.Cache generateCache(BlockBehaviour.BlockStateBase base) { if(cacheInvalid) { // Ensure that only one block's cache is built at a time synchronized (BlockBehaviour.BlockStateBase.class) { @@ -50,4 +47,32 @@ public abstract class BlockStateBaseMixin implements IBlockState { } return this.cache; } + + @Redirect(method = "*", at = @At( + value = "FIELD", + opcode = Opcodes.GETFIELD, + target = "Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase;cache:Lnet/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase$Cache;", + ordinal = 0 + )) + private BlockBehaviour.BlockStateBase.Cache dynamicCacheGen(BlockBehaviour.BlockStateBase base) { + return generateCache(base); + } + + @Dynamic + @Inject(method = "getPathNodeType", at = @At("HEAD"), require = 0, remap = false) + private void generateCacheLithium(CallbackInfoReturnable cir) { + generateCache((BlockBehaviour.BlockStateBase)(Object)this); + } + + @Dynamic + @Inject(method = "getNeighborPathNodeType", at = @At("HEAD"), require = 0, remap = false) + private void generateCacheLithium2(CallbackInfoReturnable cir) { + generateCache((BlockBehaviour.BlockStateBase)(Object)this); + } + + @Dynamic + @Inject(method = "getAllFlags", at = @At("HEAD"), require = 0, remap = false) + private void generateCacheLithium3(CallbackInfoReturnable cir) { + generateCache((BlockBehaviour.BlockStateBase)(Object)this); + } }