From 2193aa11a408251b7b5b5e03ecfadc3d166c291c Mon Sep 17 00:00:00 2001 From: embeddedt <42941056+embeddedt@users.noreply.github.com> Date: Mon, 10 Jun 2024 20:18:11 -0400 Subject: [PATCH] Add some relatively safe allocation optimizations for worldgen --- .../mixinAp/annotation/MixinProcessor.java | 3 +- .../mixinAp/config/MixinConfig.java | 4 +- .../MaterialRuleListMixin.java | 34 +++++++++++++ .../worldgen_allocation/NoiseChunkMixin.java | 34 +++++++++++++ .../SequenceRuleMixin.java | 32 ++++++++++++ .../SurfaceRulesContextMixin.java | 50 +++++++++++++++++++ .../core/config/ModernFixEarlyConfig.java | 2 +- .../world/gen/PositionalBiomeGetter.java | 36 +++++++++++++ .../main/resources/modernfix.accesswidener | 12 +++++ gradle.properties | 2 +- 10 files changed, 204 insertions(+), 5 deletions(-) create mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/MaterialRuleListMixin.java create mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/NoiseChunkMixin.java create mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/SequenceRuleMixin.java create mode 100644 common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/SurfaceRulesContextMixin.java create mode 100644 common/src/main/java/org/embeddedt/modernfix/world/gen/PositionalBiomeGetter.java diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java index 3e73ec56..14dd87ac 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/annotation/MixinProcessor.java @@ -19,6 +19,7 @@ import javax.annotation.processing.SupportedOptions; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; +import javax.lang.model.util.Elements; import javax.tools.Diagnostic; import org.fury_phoenix.mixinAp.config.MixinConfig; @@ -80,7 +81,7 @@ public class MixinProcessor extends AbstractProcessor { List mixins = annotatedMixins.stream() .map(TypeElement.class::cast) - .map(TypeElement::toString) + .map(e -> processingEnv.getElementUtils().getBinaryName(e).toString()) .collect(Collectors.toList()); mixinConfigList.putIfAbsent(aliases.get(annotation.getSimpleName().toString()), mixins); diff --git a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java index 9d1e6c91..eb3ec290 100644 --- a/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java +++ b/annotation-processor/src/main/java/org/fury_phoenix/mixinAp/config/MixinConfig.java @@ -17,7 +17,7 @@ public record MixinConfig( @SerializedName("package") String packageName, String plugin, - String compatabilityLevel, + String compatibilityLevel, @SerializedName("mixins") List commonMixins, @SerializedName("client") @@ -25,7 +25,7 @@ public record MixinConfig( InjectorOptions injectors, OverwriteOptions overwrites ) { public MixinConfig(String packageName, List commonMixins, List clientMixins) { - this(true, "0.8", packageName, "org.embeddedt.modernfix.core.ModernFixMixinPlugin", "JAVA_8", + this(true, "0.8", packageName, "org.embeddedt.modernfix.core.ModernFixMixinPlugin", "JAVA_17", commonMixins, clientMixins, InjectorOptions.DEFAULT, OverwriteOptions.DEFAULT); } public record InjectorOptions(int defaultRequire) { diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/MaterialRuleListMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/MaterialRuleListMixin.java new file mode 100644 index 00000000..83ba6cc1 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/MaterialRuleListMixin.java @@ -0,0 +1,34 @@ +package org.embeddedt.modernfix.common.mixin.perf.worldgen_allocation; + +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.DensityFunction; +import net.minecraft.world.level.levelgen.NoiseChunk; +import net.minecraft.world.level.levelgen.material.MaterialRuleList; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.List; + +@Mixin(value = MaterialRuleList.class, priority = 100) +public class MaterialRuleListMixin { + @Shadow @Final private List materialRuleList; + + /** + * @author embeddedt + * @reason Avoid iterator allocation + */ + @Overwrite + @Nullable + public BlockState calculate(DensityFunction.FunctionContext arg) { + BlockState state = null; + int s = this.materialRuleList.size(); + for(int i = 0; state == null && i < s; i++) { + NoiseChunk.BlockStateFiller blockStateFiller = this.materialRuleList.get(i); + state = blockStateFiller.calculate(arg); + } + return state; + } +} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/NoiseChunkMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/NoiseChunkMixin.java new file mode 100644 index 00000000..e6008fa0 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/NoiseChunkMixin.java @@ -0,0 +1,34 @@ +package org.embeddedt.modernfix.common.mixin.perf.worldgen_allocation; + +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import net.minecraft.world.level.levelgen.DensityFunction; +import net.minecraft.world.level.levelgen.NoiseChunk; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Map; + +@Mixin(value = NoiseChunk.class, priority = 100) +public abstract class NoiseChunkMixin { + @Shadow @Final @Mutable + private Map wrapped = new Object2ObjectOpenHashMap<>(); + + @Shadow protected abstract DensityFunction wrapNew(DensityFunction densityFunction); + + /** + * @author embeddedt + * @reason Avoid lambda allocation + */ + @Overwrite + protected DensityFunction wrap(DensityFunction unwrapped) { + DensityFunction func = this.wrapped.get(unwrapped); + if (func == null) { + func = this.wrapNew(unwrapped); + this.wrapped.put(unwrapped, func); + } + return func; + } +} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/SequenceRuleMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/SequenceRuleMixin.java new file mode 100644 index 00000000..dd084385 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/SequenceRuleMixin.java @@ -0,0 +1,32 @@ +package org.embeddedt.modernfix.common.mixin.perf.worldgen_allocation; + +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.SurfaceRules; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.List; + +@Mixin(value = SurfaceRules.SequenceRule.class, priority = 100) +public class SequenceRuleMixin { + @Shadow @Final private List rules; + + /** + * @author embeddedt + * @reason Avoid iterator allocation + */ + @Overwrite + public BlockState tryApply(int x, int y, int z) { + int s = this.rules.size(); + //noinspection ForLoopReplaceableByForEach + for(int i = 0; i < s; i++) { + BlockState state = this.rules.get(i).tryApply(x, y, z); + if(state != null) { + return state; + } + } + return null; + } +} diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/SurfaceRulesContextMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/SurfaceRulesContextMixin.java new file mode 100644 index 00000000..346722d5 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/SurfaceRulesContextMixin.java @@ -0,0 +1,50 @@ +package org.embeddedt.modernfix.common.mixin.perf.worldgen_allocation; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.world.level.biome.Biome; +import org.embeddedt.modernfix.world.gen.PositionalBiomeGetter; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.function.Function; +import java.util.function.Supplier; + +@Mixin(targets = {"net/minecraft/world/level/levelgen/SurfaceRules$Context"}, priority = 100) +public class SurfaceRulesContextMixin { + @Shadow private long lastUpdateY; + + @Shadow private int blockY; + + @Shadow private int waterHeight; + + @Shadow private int stoneDepthBelow; + + @Shadow private int stoneDepthAbove; + + @Shadow private Supplier> biome; + + @Shadow @Final private Function> biomeGetter; + + @Shadow @Final private BlockPos.MutableBlockPos pos; + + /** + * @author embeddedt + * @reason Reuse supplier object instead of creating new ones every time + */ + @Overwrite + protected void updateY(int stoneDepthAbove, int stoneDepthBelow, int waterHeight, int blockX, int blockY, int blockZ) { + ++this.lastUpdateY; + var getter = this.biome; + if(getter == null) { + this.biome = getter = new PositionalBiomeGetter(this.biomeGetter, this.pos); + } + ((PositionalBiomeGetter)getter).update(blockX, blockY, blockZ); + this.blockY = blockY; + this.waterHeight = waterHeight; + this.stoneDepthBelow = stoneDepthBelow; + this.stoneDepthAbove = stoneDepthAbove; + } +} diff --git a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java index 25c1d99a..797fec14 100644 --- a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java +++ b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java @@ -139,7 +139,7 @@ public class ModernFixEarlyConfig { mixinOptions.add(mixinCategoryName); } } catch(IOException e) { - ModernFix.LOGGER.error("Error scanning file " + mixinPath, e); + LOGGER.error("Error scanning file " + mixinPath, e); } } } diff --git a/common/src/main/java/org/embeddedt/modernfix/world/gen/PositionalBiomeGetter.java b/common/src/main/java/org/embeddedt/modernfix/world/gen/PositionalBiomeGetter.java new file mode 100644 index 00000000..6b109dcf --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/world/gen/PositionalBiomeGetter.java @@ -0,0 +1,36 @@ +package org.embeddedt.modernfix.world.gen; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; +import net.minecraft.world.level.biome.Biome; + +import java.util.function.Function; +import java.util.function.Supplier; + +public class PositionalBiomeGetter implements Supplier> { + private final Function> biomeGetter; + private final BlockPos.MutableBlockPos pos; + private int nextX, nextY, nextZ; + private volatile Holder curBiome; + + public PositionalBiomeGetter(Function> biomeGetter, BlockPos.MutableBlockPos pos) { + this.biomeGetter = biomeGetter; + this.pos = pos; + } + + public void update(int nextX, int nextY, int nextZ) { + this.nextX = nextX; + this.nextY = nextY; + this.nextZ = nextZ; + this.curBiome = null; + } + + @Override + public Holder get() { + var biome = curBiome; + if(biome == null) { + curBiome = biome = biomeGetter.apply(pos.set(nextX, nextY, nextZ)); + } + return biome; + } +} diff --git a/common/src/main/resources/modernfix.accesswidener b/common/src/main/resources/modernfix.accesswidener index 3d6d358a..e07b1b8b 100644 --- a/common/src/main/resources/modernfix.accesswidener +++ b/common/src/main/resources/modernfix.accesswidener @@ -11,6 +11,18 @@ accessible field net/minecraft/world/level/Level blockEntityTickers Ljava/util/L accessible class net/minecraft/client/renderer/RenderType$CompositeRenderType accessible method net/minecraft/nbt/CompoundTag (Ljava/util/Map;)V +accessible class net/minecraft/world/level/levelgen/SurfaceRules$SequenceRule +accessible class net/minecraft/world/level/levelgen/SurfaceRules$SurfaceRule +accessible class net/minecraft/world/level/levelgen/DensityFunctions$Marker +accessible class net/minecraft/world/level/levelgen/DensityFunctions$Marker$Type +accessible method net/minecraft/world/level/levelgen/DensityFunctions$Marker (Lnet/minecraft/world/level/levelgen/DensityFunctions$Marker$Type;Lnet/minecraft/world/level/levelgen/DensityFunction;)V +accessible class net/minecraft/world/level/levelgen/DensityFunctions$Mapped +accessible class net/minecraft/world/level/levelgen/DensityFunctions$Mapped$Type +accessible method net/minecraft/world/level/levelgen/DensityFunctions$Mapped (Lnet/minecraft/world/level/levelgen/DensityFunctions$Mapped$Type;Lnet/minecraft/world/level/levelgen/DensityFunction;DD)V +accessible class net/minecraft/world/level/levelgen/DensityFunctions$MulOrAdd +accessible class net/minecraft/world/level/levelgen/DensityFunctions$MulOrAdd$Type +accessible method net/minecraft/world/level/levelgen/DensityFunctions$MulOrAdd (Lnet/minecraft/world/level/levelgen/DensityFunctions$MulOrAdd$Type;Lnet/minecraft/world/level/levelgen/DensityFunction;DDD)V + accessible class net/minecraft/world/level/block/state/BlockBehaviour$BlockStateBase$Cache accessible class net/minecraft/server/level/ServerChunkCache$MainThreadExecutor accessible field net/minecraft/world/level/block/state/BlockBehaviour properties Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties; diff --git a/gradle.properties b/gradle.properties index 8b807342..6877f0dd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -27,7 +27,7 @@ diagonal_fences_version=4558828 spark_version=4587310 -use_fabric_api_at_runtime=true +use_fabric_api_at_runtime=false # Look up maven coordinates when changing shadow_version shadow_version=7.1.2