Skip to content

Commit

Permalink
Add allocation tweaks for low-mem and performance
Browse files Browse the repository at this point in the history
  • Loading branch information
Ampflower committed Dec 23, 2023
1 parent e756eac commit 0439dec
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 5 deletions.
8 changes: 4 additions & 4 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
projectVersion=0.0.0
minecraftVersion=1.18.2
yarnMappings=1.18.2+build.2
loaderVersion=0.13.3
minecraftVersion=1.19.2
yarnMappings=1.19.2+build.28
loaderVersion=0.14.11
org.gradle.jvmargs=-Xmx1G
systemProp.loomVersion=0.11.32
systemProp.loomVersion=1.+
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
64 changes: 64 additions & 0 deletions src/main/java/gay/ampflower/mcunsafe/MixinUnsafe.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package gay.ampflower.mcunsafe;

import net.gudenau.minecraft.asm.impl.ReflectionHelper;
import org.objectweb.asm.tree.ClassNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import org.spongepowered.asm.mixin.transformer.ClassInfo;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;

/**
* @author Ampflower
* @since ${version}
**/
public class MixinUnsafe implements IMixinConfigPlugin {
static {
try {
var $cache = ReflectionHelper.findStaticGetter(ClassInfo.class, "cache", Map.class);
var oldCache = (Map<String, ClassInfo>) $cache.invoke();
var newCache = new WeakHashMap<>(oldCache);
ReflectionHelper.findStaticSetter(ClassInfo.class, "cache", Map.class).invoke(newCache);
} catch (Throwable t) {
t.printStackTrace();
}
}

@Override
public void onLoad(String mixinPackage) {

}

@Override
public String getRefMapperConfig() {
return null;
}

@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
return false;
}

@Override
public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {

}

@Override
public List<String> getMixins() {
return null;
}

@Override
public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {

}

@Override
public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {

}
}
90 changes: 90 additions & 0 deletions src/main/java/gay/ampflower/mcunsafe/mixin/MixinModelLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package gay.ampflower.mcunsafe.mixin;

import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.AffineTransformation;
import org.apache.commons.lang3.tuple.Triple;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.Slice;

import java.util.Map;
import java.util.Set;

/**
* @author Ampflower
* @since ${version}
**/
@Mixin(ModelLoader.class)
public class MixinModelLoader {
@Shadow
@Final
@Mutable
private Set<Identifier> modelsToLoad;

@Shadow
@Final
@Mutable
private Map<Identifier, UnbakedModel> unbakedModels;

@Shadow
@Final
@Mutable
private Map<Triple<Identifier, AffineTransformation, Boolean>, BakedModel> bakedModelCache;

@Shadow
@Final
@Mutable
private Map<Identifier, UnbakedModel> modelsToBake;

@Shadow
@Final
@Mutable
private Map<Identifier, BakedModel> bakedModels;

@Redirect(method = "<init>", at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/model/ModelLoader;modelsToLoad:Ljava/util/Set;"))
private void mcunsafe$redirectModelsToLoad(ModelLoader self, Set<?> set) {
modelsToLoad = new ObjectOpenHashSet<>();
}

@Redirect(method = "<init>",
at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/model/ModelLoader;unbakedModels:Ljava/util/Map;"),
slice = @Slice(id = "primary", from = @At("HEAD"),
to = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;push(Ljava/lang/String;)V", ordinal = 0)))
private void mcunsafe$redirectUnbakedModels(ModelLoader self, Map<?, ?> map) {
unbakedModels = new Object2ObjectOpenHashMap<>(1024);
}

@Redirect(method = "<init>",
at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/model/ModelLoader;bakedModelCache:Ljava/util/Map;"),
slice = @Slice(id = "primary", from = @At("HEAD"),
to = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;push(Ljava/lang/String;)V", ordinal = 0)))
private void mcunsafe$redirectBakedModelCache(ModelLoader self, Map<?, ?> map) {
bakedModelCache = new Object2ObjectOpenHashMap<>(1024);
}

@Redirect(method = "<init>",
at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/model/ModelLoader;modelsToBake:Ljava/util/Map;"),
slice = @Slice(id = "primary", from = @At("HEAD"),
to = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;push(Ljava/lang/String;)V", ordinal = 0)))
private void mcunsafe$redirectModelsToBake(ModelLoader self, Map<?, ?> map) {
modelsToBake = new Object2ObjectOpenHashMap<>(64);
}

@Redirect(method = "<init>",
at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/model/ModelLoader;bakedModels:Ljava/util/Map;"),
slice = @Slice(id = "primary", from = @At("HEAD"),
to = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;push(Ljava/lang/String;)V", ordinal = 0)))
private void mcunsafe$redirectBakedModels(ModelLoader self, Map<?, ?> map) {
bakedModels = new Object2ObjectOpenHashMap<>(64);
}

}
37 changes: 37 additions & 0 deletions src/main/java/gay/ampflower/mcunsafe/mixin/MixinNbtCompound.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package gay.ampflower.mcunsafe.mixin;

import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.nbt.NbtCompound;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.Redirect;

import java.util.HashMap;
import java.util.Map;

/**
* @author Ampflower
* @since 0.1.0
**/
@Mixin(NbtCompound.class)
public class MixinNbtCompound {
/**
* Removes now unnecessary allocation of the map.
*/
@Redirect(method = "<init>()V", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/Maps;newHashMap()Ljava/util/HashMap;"))
private static HashMap<?, ?> mcunsafe$nullifier() {
return null;
}

/**
* Allocates FastUtil hashmap with a preallocation of 4 rather than 16.
*/
@ModifyArg(method = "<init>()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/nbt/NbtCompound;<init>(Ljava/util/Map;)V"))
private static Map<?, ?> mcunsafe$unnullifier(Map<?, ?> map) {
if (map != null) {
throw new AssertionError();
}
return new Object2ObjectOpenHashMap<>(4);
}
}
8 changes: 8 additions & 0 deletions src/main/resources/fabric.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,15 @@
"gay.ampflower.mcunsafe.asm.Asm"
]
},
"mixins": [
"mcunsafe.mixin.json"
],
"depends": {
"gud_asm": "*"
},
"custom": {
"lithium:options": {
"mixin.alloc.nbt": false
}
}
}
15 changes: 15 additions & 0 deletions src/main/resources/mcunsafe.mixin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"required": true,
"minVersion": "0.8",
"package": "gay.ampflower.mcunsafe.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"MixinNbtCompound"
],
"injectors": {
"defaultRequire": 1
},
"client": [
"MixinModelLoader"
]
}

0 comments on commit 0439dec

Please sign in to comment.