Skip to content
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

Concurrent recipe profiler #478

Merged
merged 2 commits into from
May 4, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
46 changes: 46 additions & 0 deletions src/main/java/codechicken/nei/util/AsyncTaskProfiler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
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) {
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