-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimize startup time #97
base: 1.21.1
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
package com.almostreliable.unified.utils; | ||
|
||
import com.almostreliable.unified.unification.recipe.RecipeLink; | ||
|
||
import com.google.gson.JsonArray; | ||
import com.google.gson.JsonElement; | ||
import com.google.gson.JsonObject; | ||
|
@@ -8,8 +10,6 @@ | |
import org.jetbrains.annotations.Nullable; | ||
|
||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.LinkedHashMap; | ||
|
@@ -47,8 +47,8 @@ public static JsonObject compare(Map<String, Rule> rules, JsonObject... jsonObje | |
} | ||
|
||
@Nullable | ||
public static JsonObject compareShaped(JsonObject first, JsonObject second, CompareSettings compareSettings) { | ||
if (!matches(first, second, compareSettings)) return null; | ||
public static JsonObject compareShaped(JsonObject first, JsonObject second, CompareContext compareContext) { | ||
if (!matches(first, second, compareContext)) return null; | ||
|
||
JsonArray firstPattern = JsonUtils.arrayOrSelf(first.get("pattern")); | ||
JsonArray secondPattern = JsonUtils.arrayOrSelf(second.get("pattern")); | ||
|
@@ -97,20 +97,18 @@ private static Map<Character, JsonObject> createShapedKeyMap(JsonObject json) { | |
return keyMap; | ||
} | ||
|
||
public static boolean matches(JsonObject first, JsonObject second, CompareSettings compareSettings) { | ||
Collection<String> ignoredFields = compareSettings.getIgnoredFields(); | ||
if (ignoredFields.isEmpty() && first.size() != second.size()) { | ||
public static boolean matches(JsonObject first, JsonObject second, CompareContext compareContext) { | ||
CompareSettings compareSettings = compareContext.settings; | ||
if (!compareSettings.hasIgnoredFields() && first.size() != second.size()) { | ||
return false; | ||
} | ||
|
||
for (Map.Entry<String, JsonElement> firstEntry : first.entrySet()) { | ||
if (ignoredFields.contains(firstEntry.getKey())) continue; | ||
|
||
JsonElement firstElem = firstEntry.getValue(); | ||
JsonElement secondElem = second.get(firstEntry.getKey()); | ||
|
||
for (String field : compareContext.compareFields()) { | ||
JsonElement secondElem = second.get(field); | ||
if (secondElem == null) return false; | ||
|
||
JsonElement firstElem = first.get(field); | ||
|
||
// sanitize elements for implicit counts of 1 | ||
if (compareSettings.handleImplicitCounts && needsSanitizing(firstElem, secondElem)) { | ||
firstElem = sanitize(firstElem); | ||
|
@@ -270,6 +268,17 @@ public String getName() { | |
} | ||
} | ||
|
||
public record CompareContext(CompareSettings settings, List<String> compareFields) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a specific reason you are using a list instead of a set here? Could even be a collection or iterable only. I am just asking because inside the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The PR is focused on efficiency of the hot path, which in this case (according to profiling) is the path that iterates over the The |
||
public static CompareContext create(CompareSettings settings, RecipeLink curRecipe) { | ||
Set<String> compareFields = curRecipe.getActual().keySet(); | ||
if (!settings.ignoredFields.isEmpty()) { | ||
compareFields = new HashSet<>(compareFields); | ||
compareFields.removeAll(settings.ignoredFields); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Checking the ignored fields happens so frequently that it slows down loading. |
||
} | ||
return new CompareContext(settings, List.copyOf(compareFields)); | ||
} | ||
} | ||
|
||
public static class CompareSettings { | ||
|
||
public static final String IGNORED_FIELDS = "ignored_fields"; | ||
|
@@ -292,8 +301,8 @@ public void addRule(String key, Rule rule) { | |
} | ||
} | ||
|
||
public Set<String> getIgnoredFields() { | ||
return Collections.unmodifiableSet(ignoredFields); | ||
public boolean hasIgnoredFields() { | ||
return !ignoredFields.isEmpty(); | ||
} | ||
|
||
public JsonObject serialize() { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this gets called so much that the capturing lambda actually caused a minor performance hit, so I turned this
computeIfAbsent
into a regularget/put
sequence