diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/mojang_registry_size/MappedRegistryMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/mojang_registry_size/MappedRegistryMixin.java new file mode 100644 index 00000000..ad9adc3c --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/mojang_registry_size/MappedRegistryMixin.java @@ -0,0 +1,36 @@ +package org.embeddedt.modernfix.common.mixin.perf.mojang_registry_size; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import it.unimi.dsi.fastutil.objects.ObjectList; +import net.minecraft.core.MappedRegistry; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(MappedRegistry.class) +public class MappedRegistryMixin { + /** + * Avoid copying the ID list to a slightly larger one every time an entry is added to the registry. + * The original behavior causes O(n) time complexity for registration. + */ + @Redirect( + method = "registerMapping(ILnet/minecraft/resources/ResourceKey;Ljava/lang/Object;Lcom/mojang/serialization/Lifecycle;Z)Ljava/lang/Object;", + at = @At(value = "INVOKE", target = "Lit/unimi/dsi/fastutil/objects/ObjectList;size(I)V") + ) + private void setSizeSmart(ObjectList list, int size) { + if(list instanceof ObjectArrayList && size > list.size()) { + int requestedSize = size; + /* choose next power of two, or this value if it is a power of two */ + int p2Size = Integer.highestOneBit(size); + if(p2Size != size) + size = p2Size << 1; + // grow backing array to power-of-two size, this will return instantly in most cases + ((ObjectArrayList)list).ensureCapacity(size); + // write null entries to fill size, to match the behavior of list.size(int) + while(list.size() < requestedSize) + list.add(null); + } else { + list.size(size); + } + } +} diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/fast_registry_validation/ResourceKeyMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/mojang_registry_size/ResourceKeyMixin.java similarity index 85% rename from forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/fast_registry_validation/ResourceKeyMixin.java rename to common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/mojang_registry_size/ResourceKeyMixin.java index 0c62d3fe..7d6701db 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/perf/fast_registry_validation/ResourceKeyMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/mojang_registry_size/ResourceKeyMixin.java @@ -1,4 +1,4 @@ -package org.embeddedt.modernfix.forge.mixin.perf.fast_registry_validation; +package org.embeddedt.modernfix.common.mixin.perf.mojang_registry_size; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.minecraft.resources.ResourceKey; @@ -12,7 +12,7 @@ import java.util.Map; @Mixin(ResourceKey.class) public class ResourceKeyMixin { - private static Map>> INTERNING_MAP = new Object2ObjectOpenHashMap<>(); + private static final Map>> INTERNING_MAP = new Object2ObjectOpenHashMap<>(); @Inject(method = "create(Lnet/minecraft/resources/ResourceLocation;Lnet/minecraft/resources/ResourceLocation;)Lnet/minecraft/resources/ResourceKey;", at = @At("HEAD"), cancellable = true) private static void createEfficient(ResourceLocation parent, ResourceLocation location, CallbackInfoReturnable> cir) { synchronized (ResourceKey.class) {