Compare commits

...
2 Commits
Author SHA1 Message Date
Martin Robertz 3fecc84f59 update
(cherry picked from commit d05a9eafb3)
2024-05-04 21:08:22 +02:00
Lasm Gratel cba4cb7856 Concurrent recipe profiler (#478)
* concurrent recipe profiler

* eliminate NPE by giving nulls a name

(cherry picked from commit 5056fe5437)
2024-05-04 21:08:17 +02:00
8 changed files with 78 additions and 19 deletions

No files matched your search

+1 -1
View File
@@ -17,7 +17,7 @@ pluginManagement {
}
plugins {
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.21'
id 'com.gtnewhorizons.gtnhsettingsconvention' version '1.0.22'
}
@@ -34,7 +34,9 @@ public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
final BookmarkRecipeId recipeId;
if ("item".equals(outputId)) {
results = Arrays.asList(results).stream().map(rslt -> normalizeItemStack((ItemStack) rslt)).toArray();
for (int i = 0; i < results.length; i++) {
results[i] = normalizeItemStack((ItemStack) results[i]);
}
recipeId = getRecipeId(mc.currentScreen, (ItemStack) results[0]);
} else if ("recipeId".equals(outputId)) {
recipeId = (BookmarkRecipeId) results[1];
@@ -103,7 +105,7 @@ public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
"outputId: " + outputId,
"results: " + Arrays.toString(results));
return recipeQuery.runWithProfiling("recipe.concurrent.crafting");
return recipeQuery.runWithProfiling(NEIClientUtils.translate("recipe.concurrent.crafting"));
}
private static ArrayList<ICraftingHandler> filterByHandlerName(ArrayList<ICraftingHandler> craftinghandlers,
@@ -18,8 +18,9 @@ public class GuiUsageRecipe extends GuiRecipe<IUsageHandler> {
public static boolean openRecipeGui(String inputId, Object... ingredients) {
if ("item".equals(inputId)) {
ingredients = Arrays.asList(ingredients).stream().map(ingr -> normalizeItemStack((ItemStack) ingr))
.toArray();
for (int i = 0; i < ingredients.length; i++) {
ingredients[i] = normalizeItemStack((ItemStack) ingredients[i]);
}
}
final ArrayList<IUsageHandler> handlers = getUsageHandlers(inputId, ingredients);
@@ -52,7 +53,7 @@ public class GuiUsageRecipe extends GuiRecipe<IUsageHandler> {
"inputId: " + inputId,
"ingredients: " + Arrays.toString(ingredients));
return recipeQuery.runWithProfiling("recipe.concurrent.usage");
return recipeQuery.runWithProfiling(NEIClientUtils.translate("recipe.concurrent.usage"));
}
private static ItemStack normalizeItemStack(ItemStack stack) {
@@ -81,7 +81,7 @@ class ItemsHistoryHandler implements ICraftingHandler, IUsageHandler {
@Override
public String getRecipeName() {
return null;
return "Items History";
}
@Override
@@ -3,29 +3,26 @@ package codechicken.nei.recipe;
import static codechicken.lib.gui.GuiDraw.drawString;
import static codechicken.lib.gui.GuiDraw.getStringWidth;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.inventory.Container;
import net.minecraft.item.ItemStack;
import codechicken.core.TaskProfiler;
import codechicken.core.TaskProfiler.ProfilerResult;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.PositionedStack;
import codechicken.nei.api.IOverlayHandler;
import codechicken.nei.api.IRecipeOverlayRenderer;
import codechicken.nei.util.AsyncTaskProfiler;
public class ProfilerRecipeHandler implements ICraftingHandler, IUsageHandler {
private static final TaskProfiler profiler = new TaskProfiler();
private static final AsyncTaskProfiler profiler = new AsyncTaskProfiler();
public static TaskProfiler getProfiler() {
profiler.clear();
public static AsyncTaskProfiler getProfiler() {
return profiler;
}
@@ -55,8 +52,7 @@ public class ProfilerRecipeHandler implements ICraftingHandler, IUsageHandler {
@Override
public void drawForeground(int recipe) {
List<ProfilerResult> results = profiler.getResults();
for (Iterator<ProfilerResult> it = results.iterator(); it.hasNext();)
if (it.next().name.equals(getRecipeName())) it.remove();
results.removeIf(profilerResult -> getRecipeName().equals(profilerResult.name));
results.sort((o1, o2) -> o1.time < o2.time ? 1 : -1);
@@ -65,10 +61,9 @@ public class ProfilerRecipeHandler implements ICraftingHandler, IUsageHandler {
int y = (i % 6) * 20 + 6;
drawString(r.name, 8, y, 0xFF808080, false);
DecimalFormat format = new DecimalFormat("0.00");
String s = format.format(r.fraction * 100) + "%";
if (r.time < 1000000L) s += " (" + (r.time / 1000) + "us)";
else s += " (" + (r.time / 1000000) + "ms)";
String s;
if (r.time < 1000000L) s = (r.time / 1000) + "us";
else s = (r.time / 1000000) + "ms";
drawString(s, 156 - getStringWidth(s), y + 10, 0xFF404040, false);
}
@@ -15,6 +15,7 @@ import net.minecraft.util.IChatComponent;
import codechicken.core.TaskProfiler;
import codechicken.nei.ItemList;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.util.AsyncTaskProfiler;
class RecipeHandlerQuery<T extends IRecipeHandler> {
@@ -34,6 +35,7 @@ class RecipeHandlerQuery<T extends IRecipeHandler> {
ArrayList<T> runWithProfiling(String profilerSection) {
TaskProfiler profiler = ProfilerRecipeHandler.getProfiler();
profiler.clear();
profiler.start(profilerSection);
try {
ArrayList<T> handlers = getRecipeHandlersParallel();
@@ -63,12 +65,17 @@ class RecipeHandlerQuery<T extends IRecipeHandler> {
private ArrayList<T> getSerialHandlersWithRecipes() {
return serialRecipeHandlers.stream().map(handler -> {
AsyncTaskProfiler profiler = ProfilerRecipeHandler.getProfiler();
profiler.clearCurrent();
profiler.start(handler.getRecipeName());
try {
return isHidden(handler) ? null : recipeHandlerFunction.apply(handler);
} catch (Throwable t) {
printLog(t);
error = true;
return null;
} finally {
profiler.end();
}
}).filter(h -> h != null && h.numRecipes() > 0 && SearchRecipeHandler.findFirst(h, (recipeIndex) -> true) != -1)
.collect(Collectors.toCollection(ArrayList::new));
@@ -77,12 +84,17 @@ class RecipeHandlerQuery<T extends IRecipeHandler> {
private ArrayList<T> getHandlersWithRecipes() throws InterruptedException, ExecutionException {
return ItemList.forkJoinPool.submit(() -> recipeHandlers.parallelStream().map(handler -> {
AsyncTaskProfiler profiler = ProfilerRecipeHandler.getProfiler();
profiler.clearCurrent();
profiler.start(handler.getRecipeName());
try {
return isHidden(handler) ? null : recipeHandlerFunction.apply(handler);
} catch (Throwable t) {
printLog(t);
error = true;
return null;
} finally {
profiler.end();
}
}).filter(h -> h != null && h.numRecipes() > 0 && SearchRecipeHandler.findFirst(h, (recipeIndex) -> true) != -1)
.collect(Collectors.toCollection(ArrayList::new))).get();
@@ -0,0 +1,47 @@
package codechicken.nei.util;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import codechicken.core.TaskProfiler;
public class AsyncTaskProfiler extends TaskProfiler {
public ThreadLocal<TaskProfiler> threadedProfiler = ThreadLocal.withInitial(TaskProfiler::new);
public Map<String, Long> times = new ConcurrentHashMap<>();
public void start(String section) {
if (section == null) section = "<unnamed>";
threadedProfiler.get().start(section);
}
public void end() {
threadedProfiler.get().end();
times.putAll(threadedProfiler.get().times);
}
@Override
public List<ProfilerResult> getResults() {
ArrayList<ProfilerResult> results = new ArrayList<>(times.size());
long totalTime = times.values().stream().reduce(0L, Long::sum);
for (Entry<String, Long> e : times.entrySet())
results.add(new ProfilerResult(e.getKey(), e.getValue(), totalTime));
return results;
}
@Override
public void clear() {
if (threadedProfiler.get().currentSection != null) threadedProfiler.get().end();
threadedProfiler.get().clear();
times.clear();
}
public void clearCurrent() {
if (threadedProfiler.get().currentSection != null) threadedProfiler.get().end();
threadedProfiler.get().clear();
}
}
@@ -321,6 +321,8 @@ nei.recipe.firework.tooltip2=Multiple charges can be spawned from one rocket
nei.recipe.brewing=Brewing
nei.recipe.profiler.crafting=Crafting Profiling
nei.recipe.profiler.usage=Usage Profiling
nei.recipe.concurrent.usage=Concurrent Usage - Total
nei.recipe.concurrent.crafting=Concurrent Crafting - Total
nei.itemsort.minecraft=Minecraft
nei.itemsort.minecraft.tip=Sorts items from vanilla minecraft first