Skip to content

Commit

Permalink
Concurrent recipe profiler (#478)
Browse files Browse the repository at this point in the history
* concurrent recipe profiler

* eliminate NPE by giving nulls a name
  • Loading branch information
LasmGratel authored May 4, 2024
1 parent 9fd9aad commit 5056fe5
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 18 deletions.
6 changes: 4 additions & 2 deletions src/main/java/codechicken/nei/recipe/GuiCraftingRecipe.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ public static GuiRecipe<?> createRecipeGui(String outputId, boolean open, Object
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];
Expand Down Expand Up @@ -103,7 +105,7 @@ public static ArrayList<ICraftingHandler> getCraftingHandlers(String outputId, O
"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,
Expand Down
7 changes: 4 additions & 3 deletions src/main/java/codechicken/nei/recipe/GuiUsageRecipe.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -52,7 +53,7 @@ public static ArrayList<IUsageHandler> getUsageHandlers(String inputId, Object..
"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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public boolean mouseClicked(GuiRecipe gui, int button, int recipe) {

@Override
public String getRecipeName() {
return null;
return "Items History";
}

@Override
Expand Down
19 changes: 7 additions & 12 deletions src/main/java/codechicken/nei/recipe/ProfilerRecipeHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,26 @@
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;
}

Expand Down Expand Up @@ -55,8 +52,7 @@ public void drawBackground(int recipe) {}
@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);

Expand All @@ -65,10 +61,9 @@ public void drawForeground(int recipe) {
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);
}
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/codechicken/nei/recipe/RecipeHandlerQuery.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import codechicken.core.TaskProfiler;
import codechicken.nei.ItemList;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.util.AsyncTaskProfiler;

class RecipeHandlerQuery<T extends IRecipeHandler> {

Expand All @@ -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();
Expand Down Expand Up @@ -63,12 +65,17 @@ private ArrayList<T> getRecipeHandlersParallel() throws InterruptedException, Ex
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));
Expand All @@ -77,12 +84,17 @@ private ArrayList<T> getSerialHandlersWithRecipes() {
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();
Expand Down
47 changes: 47 additions & 0 deletions src/main/java/codechicken/nei/util/AsyncTaskProfiler.java
Original file line number Diff line number Diff line change
@@ -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();
}
}
2 changes: 2 additions & 0 deletions src/main/resources/assets/nei/lang/en_US.lang
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 5056fe5

Please sign in to comment.