Add some relatively safe allocation optimizations for worldgen

This commit is contained in:
embeddedt 2024-06-10 20:18:11 -04:00
parent 1ec9aad47f
commit 2193aa11a4
No known key found for this signature in database
GPG Key ID: A69433EC199B5613
10 changed files with 204 additions and 5 deletions

View File

@ -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<String> 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);

View File

@ -17,7 +17,7 @@ public record MixinConfig(
@SerializedName("package")
String packageName,
String plugin,
String compatabilityLevel,
String compatibilityLevel,
@SerializedName("mixins")
List<String> commonMixins,
@SerializedName("client")
@ -25,7 +25,7 @@ public record MixinConfig(
InjectorOptions injectors, OverwriteOptions overwrites
) {
public MixinConfig(String packageName, List<String> commonMixins, List<String> 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) {

View File

@ -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<NoiseChunk.BlockStateFiller> 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;
}
}

View File

@ -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<DensityFunction, DensityFunction> 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;
}
}

View File

@ -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<SurfaceRules.SurfaceRule> 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;
}
}

View File

@ -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<Holder<Biome>> biome;
@Shadow @Final private Function<BlockPos, Holder<Biome>> 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;
}
}

View File

@ -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);
}
}
}

View File

@ -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<Holder<Biome>> {
private final Function<BlockPos, Holder<Biome>> biomeGetter;
private final BlockPos.MutableBlockPos pos;
private int nextX, nextY, nextZ;
private volatile Holder<Biome> curBiome;
public PositionalBiomeGetter(Function<BlockPos, Holder<Biome>> 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<Biome> get() {
var biome = curBiome;
if(biome == null) {
curBiome = biome = biomeGetter.apply(pos.set(nextX, nextY, nextZ));
}
return biome;
}
}

View File

@ -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 <init> (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 <init> (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 <init> (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 <init> (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;

View File

@ -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