Skip to content

Commit

Permalink
Optimize TooltipItemFilter; ItemFilter limited cache (#565)
Browse files Browse the repository at this point in the history
Co-authored-by: slprime <history-21@yandex.ru>
Co-authored-by: Martin Robertz <dream-master@gmx.net>
  • Loading branch information
3 people authored Dec 7, 2024
1 parent b5d2815 commit c305649
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 49 deletions.
72 changes: 62 additions & 10 deletions src/main/java/codechicken/nei/SearchTokenParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -86,6 +88,47 @@ public boolean matches(ItemStack item) {
}
}

private static class ItemFilterCache implements ItemFilter {

public ItemFilter filter;
private final ItemStackMap<Boolean> states = new ItemStackMap<>();
private final ReentrantLock lock = new ReentrantLock();

public ItemFilterCache(ItemFilter filter) {
this.filter = filter;
}

@Override
public boolean matches(ItemStack item) {
lock.lock();

try {
Boolean match = states.get(item);

if (match == null) {
states.put(item, match = this.filter.matches(item));
}

return match;
} catch (Throwable th) {
th.printStackTrace();
return false;
} finally {
lock.unlock();
}
}
}

private static final LinkedHashMap<String, ItemFilter> filtersCache = new LinkedHashMap<>() {

private static final long serialVersionUID = 1042213947848622164L;

@Override
protected boolean removeEldestEntry(Map.Entry<String, ItemFilter> eldest) {
return size() > 20;
}
};

protected final List<ISearchParserProvider> searchProviders;
protected final ProvidersCache providersCache = new ProvidersCache();
protected final TCharCharMap prefixRedefinitions = new TCharCharHashMap();
Expand Down Expand Up @@ -134,17 +177,26 @@ && getRedefinedPrefix(provider.getPrefix()) == ch)
}

public ItemFilter getFilter(String filterText) {
final String[] parts = EnumChatFormatting.getTextWithoutFormattingCodes(filterText).toLowerCase().split("\\|");
final List<ItemFilter> searchTokens = Arrays.stream(parts).map(this::parseSearchText).filter(s -> s != null)
.collect(Collectors.toCollection(ArrayList::new));

if (searchTokens.isEmpty()) {
return new EverythingItemFilter();
} else if (searchTokens.size() == 1) {
return new IsRegisteredItemFilter(searchTokens.get(0));
} else {
return new IsRegisteredItemFilter(new AnyMultiItemFilter(searchTokens));

if (!filtersCache.containsKey(filterText)) {
final String[] parts = EnumChatFormatting.getTextWithoutFormattingCodes(filterText).toLowerCase()
.split("\\|");
final List<ItemFilter> searchTokens = Arrays.stream(parts).map(this::parseSearchText).filter(s -> s != null)
.collect(Collectors.toCollection(ArrayList::new));

if (searchTokens.isEmpty()) {
filtersCache.put(filterText, new EverythingItemFilter());
} else if (searchTokens.size() == 1) {
filtersCache.put(filterText, new IsRegisteredItemFilter(new ItemFilterCache(searchTokens.get(0))));
} else {
filtersCache.put(
filterText,
new IsRegisteredItemFilter(new ItemFilterCache(new AnyMultiItemFilter(searchTokens))));
}

}

return filtersCache.get(filterText);
}

public Pattern getSplitPattern() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.recipe.StackInfo;
import codechicken.nei.search.TooltipFilter;
import codechicken.nei.util.ReadableNumberConverter;

public class GuiContainerManager {
Expand All @@ -53,6 +54,7 @@ private static class ResourcePackReloaded implements IResourceManagerReloadListe
@Override
public void onResourceManagerReload(IResourceManager p_110549_1_) {
renderingErrorItems.clear();
TooltipFilter.populateSearchMap();
}
}

Expand Down
64 changes: 25 additions & 39 deletions src/main/java/codechicken/nei/search/TooltipFilter.java
Original file line number Diff line number Diff line change
@@ -1,48 +1,21 @@
package codechicken.nei.search;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Pattern;

import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;

import codechicken.nei.ItemList;
import codechicken.nei.ItemStackMap;
import codechicken.nei.api.ItemFilter;
import codechicken.nei.guihook.GuiContainerManager;

public class TooltipFilter implements ItemFilter {

// lookup optimisation
private static final ConcurrentHashMap<ItemStackKey, String> itemSearchNames = new ConcurrentHashMap<>();

private static class ItemStackKey {

public final ItemStack stack;

public ItemStackKey(ItemStack stack) {
this.stack = stack;
}

@Override
public int hashCode() {
if (this.stack == null) return 1;
int hashCode = 1;
hashCode = 31 * hashCode + stack.stackSize;
hashCode = 31 * hashCode + Item.getIdFromItem(stack.getItem());
hashCode = 31 * hashCode + stack.getItemDamage();
hashCode = 31 * hashCode + (!stack.hasTagCompound() ? 0 : stack.getTagCompound().hashCode());
return hashCode;
}

@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof ItemStackKey)) return false;
return ItemStack.areItemStacksEqual(this.stack, ((ItemStackKey) o).stack);
}
}
private static final ItemStackMap<String> itemSearchNames = new ItemStackMap<>();
private static final ReentrantLock lock = new ReentrantLock();

private final Pattern pattern;

Expand All @@ -56,17 +29,30 @@ public boolean matches(ItemStack itemStack) {
}

public static void populateSearchMap() {
new Thread("NEI populate Tooltip Filter") {

@Override
public void run() {
ItemList.items.parallelStream().forEach(TooltipFilter::getSearchTooltip);
}
}.start();
itemSearchNames.clear();
new Thread(
() -> ItemList.items.parallelStream().forEach(TooltipFilter::getSearchTooltip),
"NEI populate Tooltip Filter").start();
}

protected static String getSearchTooltip(ItemStack stack) {
return itemSearchNames.computeIfAbsent(new ItemStackKey(stack), key -> getTooltip(key.stack));
lock.lock();

try {
String tooltip = itemSearchNames.get(stack);

if (tooltip == null) {
tooltip = getTooltip(stack.copy());
itemSearchNames.put(stack, tooltip);
}

return tooltip;
} catch (Throwable th) {
th.printStackTrace();
return "";
} finally {
lock.unlock();
}
}

private static String getTooltip(ItemStack itemstack) {
Expand Down

0 comments on commit c305649

Please sign in to comment.