From 71971a01ca9ff09d220a49970255069a8efe0046 Mon Sep 17 00:00:00 2001 From: AlexIIL Date: Wed, 25 Dec 2019 13:01:21 +0000 Subject: Optimise EntryRegistryImpl.registerEntries by first checking in a set to see if the given entry already exists before adding it, instead of looping through the whole list to see if any of them match. --- .../java/me/shedaniel/rei/api/EntryRegistry.java | 11 +++ src/main/java/me/shedaniel/rei/api/EntryStack.java | 5 ++ .../me/shedaniel/rei/impl/EntryRegistryImpl.java | 78 ++++++++++++++++++---- .../java/me/shedaniel/rei/impl/ItemEntryStack.java | 20 ++++-- .../me/shedaniel/rei/plugin/DefaultPlugin.java | 4 +- 5 files changed, 98 insertions(+), 20 deletions(-) (limited to 'src/main') diff --git a/src/main/java/me/shedaniel/rei/api/EntryRegistry.java b/src/main/java/me/shedaniel/rei/api/EntryRegistry.java index 1a8c5f157..a7765036d 100644 --- a/src/main/java/me/shedaniel/rei/api/EntryRegistry.java +++ b/src/main/java/me/shedaniel/rei/api/EntryRegistry.java @@ -10,6 +10,7 @@ import me.shedaniel.rei.utils.CollectionUtils; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import java.util.Collection; import java.util.List; public interface EntryRegistry { @@ -72,6 +73,16 @@ public interface EntryRegistry { } } + /** + * Registers multiple stacks to the item list + * + * @param afterStack the stack to put after + * @param stacks the stacks to register + */ + default void registerEntriesAfter(EntryStack afterStack, Collection stacks) { + registerEntriesAfter(afterStack, stacks.toArray(new EntryStack[0])); + } + /** * Registers multiple stacks to the item list * diff --git a/src/main/java/me/shedaniel/rei/api/EntryStack.java b/src/main/java/me/shedaniel/rei/api/EntryStack.java index 926ad28a8..8fd4a135a 100644 --- a/src/main/java/me/shedaniel/rei/api/EntryStack.java +++ b/src/main/java/me/shedaniel/rei/api/EntryStack.java @@ -127,6 +127,11 @@ public interface EntryStack { boolean equalsAll(EntryStack stack); + /** {@link #hashCode()} for {@link #equalsAll(EntryStack)}. */ + default int hashOfAll() { + return hashCode(); + } + int getZ(); void setZ(int z); diff --git a/src/main/java/me/shedaniel/rei/impl/EntryRegistryImpl.java b/src/main/java/me/shedaniel/rei/impl/EntryRegistryImpl.java index b9053e547..7fd4f8d1b 100644 --- a/src/main/java/me/shedaniel/rei/impl/EntryRegistryImpl.java +++ b/src/main/java/me/shedaniel/rei/impl/EntryRegistryImpl.java @@ -13,16 +13,39 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.DefaultedList; +import it.unimi.dsi.fastutil.Hash; +import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet; +import it.unimi.dsi.fastutil.objects.ObjectSets; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.List; -import java.util.TreeSet; +import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.stream.Collectors; @Deprecated @Internal public class EntryRegistryImpl implements EntryRegistry { private final CopyOnWriteArrayList entries = Lists.newCopyOnWriteArrayList(); + private final Set entrySet = ObjectSets.synchronize(new ObjectOpenCustomHashSet<>(new Hash.Strategy() { + @Override + public int hashCode(EntryStack entry) { + return entry == null ? 0 : entry.hashOfAll(); + } + + @Override + public boolean equals(EntryStack a, EntryStack b) { + if (a == null || b == null) { + return a == b; + } else { + boolean result = a.equalsAll(b); + assert result == b.equalsAll(a) : "a.equalsAll(b) != b.equalsAll(a); (a = " + a + ", b = " + b + ")"; + return result; + } + } + })); @Override public List getStacksList() { @@ -34,23 +57,52 @@ public class EntryRegistryImpl implements EntryRegistry { DefaultedList list = DefaultedList.of(); list.add(item.getStackForRender()); item.appendStacks(item.getGroup(), list); - TreeSet stackSet = list.stream().collect(Collectors.toCollection(() -> new TreeSet((p1, p2) -> ItemStack.areEqualIgnoreDamage(p1, p2) ? 0 : 1))); - return Lists.newArrayList(stackSet).toArray(new ItemStack[0]); + ItemStack[] array = list.toArray(new ItemStack[0]); + Arrays.sort(array, (a, b) -> ItemStack.areEqualIgnoreDamage(a, b) ? 0 : 1); + return array; } @Override @Deprecated public void registerEntryAfter(EntryStack afterEntry, EntryStack stack, boolean checkAlreadyContains) { - if (!stack.isEmpty() && (!checkAlreadyContains || !alreadyContain(stack))) - if (afterEntry == null || afterEntry.isEmpty()) - entries.add(stack); - else { - int last = entries.size(); - for (int i = 0; i < entries.size(); i++) - if (entries.get(i).equalsAll(afterEntry)) - last = i + 1; - entries.add(last, stack); + if (stack.isEmpty()) return; + boolean isNew = entrySet.add(stack); + if (checkAlreadyContains && !isNew) { + return; + } + if (afterEntry == null) { + entries.add(stack); + } else { + int last = entries.size(); + for (int i = 0; i < entries.size(); i++) + if (entries.get(i).equalsAll(afterEntry)) + last = i + 1; + entries.add(last, stack); + } + } + + @Override + public void registerEntriesAfter(EntryStack afterStack, Collection stacks) { + List nonDuplicates = new ArrayList<>(); + for (EntryStack stack : stacks) { + if (entrySet.add(stack)) { + nonDuplicates.add(stack); + } + } + int index = entries.size(); + if (afterStack != null) { + for (int i = index - 1; i >= 0; i--) { + if (entries.get(i).equalsAll(afterStack)) { + index = i + 1; + break; + } } + } + entries.addAll(index, nonDuplicates); } + @Override + public void registerEntriesAfter(EntryStack afterStack, EntryStack... stacks) { + registerEntriesAfter(afterStack, Arrays.asList(stacks)); + } } diff --git a/src/main/java/me/shedaniel/rei/impl/ItemEntryStack.java b/src/main/java/me/shedaniel/rei/impl/ItemEntryStack.java index 5aa6d7072..3778cd5f0 100644 --- a/src/main/java/me/shedaniel/rei/impl/ItemEntryStack.java +++ b/src/main/java/me/shedaniel/rei/impl/ItemEntryStack.java @@ -34,6 +34,7 @@ import java.util.Optional; public class ItemEntryStack extends AbstractEntryStack { private ItemStack itemStack; + private int hash = -1; public ItemEntryStack(ItemStack itemStack) { this.itemStack = itemStack; @@ -57,6 +58,7 @@ public class ItemEntryStack extends AbstractEntryStack { @Override public void setAmount(int amount) { itemStack.setCount(amount); + hash = -1; } @Override @@ -114,12 +116,18 @@ public class ItemEntryStack extends AbstractEntryStack { @Override public int hashCode() { - int result = 1; - result = 31 * result + getType().ordinal(); - result = 31 * result + itemStack.getItem().hashCode(); - result = 31 * result + itemStack.getCount(); - result = 31 * result + (itemStack.hasTag() ? itemStack.getTag().hashCode() : 0); - return result; + if (hash == -1) { + int result = 1; + result = 31 * result + getType().ordinal(); + result = 31 * result + itemStack.getItem().hashCode(); + result = 31 * result + itemStack.getCount(); + result = 31 * result + (itemStack.hasTag() ? itemStack.getTag().hashCode() : 0); + hash = result; + if (hash == -1) { + hash = -2; + } + } + return hash; } @Nullable diff --git a/src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java b/src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java index feb52f347..c0ccf527b 100644 --- a/src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java +++ b/src/main/java/me/shedaniel/rei/plugin/DefaultPlugin.java @@ -110,15 +110,17 @@ public class DefaultPlugin implements REIPluginV0 { entryRegistry.registerEntry(EntryStack.create(item)); } EntryStack stack = EntryStack.create(Items.ENCHANTED_BOOK); + List enchantments = new ArrayList<>(); for (Enchantment enchantment : Registry.ENCHANTMENT) { for (int i = enchantment.getMinimumLevel(); i <= enchantment.getMaximumLevel(); i++) { Map map = new HashMap<>(); map.put(enchantment, i); ItemStack itemStack = new ItemStack(Items.ENCHANTED_BOOK); EnchantmentHelper.set(map, itemStack); - entryRegistry.registerEntriesAfter(stack, EntryStack.create(itemStack)); + enchantments.add(EntryStack.create(itemStack)); } } + entryRegistry.registerEntriesAfter(stack, enchantments); for (Fluid fluid : Registry.FLUID) { if (!(fluid instanceof EmptyFluid)) entryRegistry.registerEntry(EntryStack.create(fluid)); -- cgit