13
0

Improve performance + Flatten recursion

Dieser Commit ist enthalten in:
Lixfel 2022-03-30 18:06:52 +02:00
Ursprung 230209436d
Commit cf76202775
2 geänderte Dateien mit 37 neuen und 35 gelöschten Zeilen

Datei anzeigen

@ -14,12 +14,15 @@ public class Sampler {
private static final Set<String> waitingMethods = new HashSet<>(); private static final Set<String> waitingMethods = new HashSet<>();
static { static {
waitingMethods.add("io.netty.channel.epoll.Native.epollWait"); waitingMethods.add("io.netty.channel.epoll.Native.epollWait:-2");
waitingMethods.add("org.jline.utils.NonBlockingInputStream.read"); waitingMethods.add("io.netty.channel.epoll.Native.epollWait0:-2");
waitingMethods.add("org.bukkit.craftbukkit.libs.jline.internal.NonBlockingInputStream.read"); //waitingMethods.add("org.jline.utils.NonBlockingInputStream.read");
waitingMethods.add("org.bukkit.craftbukkit.v1_15_R1.util.TerminalConsoleWriterThread.run"); waitingMethods.add("org.bukkit.craftbukkit.libs.jline.internal.NonBlockingInputStream.read:248");
waitingMethods.add("sun.nio.ch.SocketDispatcher.read0"); //waitingMethods.add("org.bukkit.craftbukkit.v1_15_R1.util.TerminalConsoleWriterThread.run");
waitingMethods.add("openj9.internal.tools.attach.target.IPC.waitSemaphore"); waitingMethods.add("net.minecraft.terminalconsole.SimpleTerminalConsole.readCommands:180");
waitingMethods.add("sun.nio.ch.SocketDispatcher.read0:-2");
waitingMethods.add("openj9.internal.tools.attach.target.IPC.waitSemaphore:-2");
waitingMethods.add("sun.nio.ch.Net.poll:-2");
} }
private static final List<String> omittedMethods = new ArrayList<>(); private static final List<String> omittedMethods = new ArrayList<>();
@ -91,30 +94,39 @@ public class Sampler {
sampleRuns++; sampleRuns++;
Map<Thread, StackTraceElement[]> stackTraces = Thread.getAllStackTraces(); Map<Thread, StackTraceElement[]> stackTraces = Thread.getAllStackTraces();
List<StackTraceElement> filteredStack = new LinkedList<>(); Set<String> previousIds = new HashSet<>();
for(Map.Entry<Thread, StackTraceElement[]> entry : stackTraces.entrySet()) { for(Map.Entry<Thread, StackTraceElement[]> entry : stackTraces.entrySet()) {
Thread thread = entry.getKey(); Thread thread = entry.getKey();
StackTraceElement[] stack = entry.getValue(); StackTraceElement[] stack = entry.getValue();
if(stack.length == 0 || thread.getName().equals("Sampler")) String threadName = thread.getName();
if(stack.length == 0 || threadName.equals("Sampler"))
continue; continue;
previousIds.clear();
Thread.State state = thread.getState(); Thread.State state = thread.getState();
filteredStack.clear(); String[] ids = new String[stack.length];
for(StackTraceElement ste : stack) { for(int i = 0; i < stack.length; i++) {
String id = ste.getClassName() + "." + ste.getMethodName(); StackTraceElement ste = stack[i];
String id = ste.getClassName() + "." + ste.getMethodName() + ":" + ste.getLineNumber();
ids[i] = id;
if (waitingMethods.contains(id)) if (waitingMethods.contains(id))
state = Thread.State.WAITING; state = Thread.State.WAITING;
if(omittedMethods.stream().noneMatch(id::startsWith))
filteredStack.add(0, ste);
} }
Trace predecessor = traces.computeIfAbsent(thread.getName(), name -> new Trace(this, thread)); Trace predecessor = traces.computeIfAbsent(threadName, name -> new Trace(this, threadName));
predecessor.add(state, null); predecessor.add(state, null);
for(StackTraceElement ste : filteredStack) { for(int i = stack.length - 1; i >= 0; i--) {
Trace trace = traces.computeIfAbsent(ste.getClassName() + "." + ste.getMethodName() + ":" + ste.getLineNumber(), id -> new Trace(this, ste)); String id = ids[i];
if(!previousIds.add(id) || omittedMethods.stream().anyMatch(id::startsWith))
continue;
Trace trace = traces.computeIfAbsent(id, id1 -> new Trace(this, id1));
trace.add(state, predecessor); trace.add(state, predecessor);
predecessor = trace; predecessor = trace;
} }

Datei anzeigen

@ -3,7 +3,7 @@ package de.steamwar;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStreamWriter; import java.io.OutputStreamWriter;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.EnumMap; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -16,19 +16,9 @@ public class Trace {
private final int id; private final int id;
private final String name; private final String name;
private final Map<Thread.State, Integer> samples = new EnumMap<>(Thread.State.class); private final int[] samples = new int[6];
private final Map<Trace, Integer> predecessors = new HashMap<>(); private final Map<Trace, Integer> predecessors = new HashMap<>();
public Trace(Sampler sampler, StackTraceElement ste) {
this.sampler = sampler;
id = idCounter++;
name = ste.getClassName() + "." + ste.getMethodName() + ":" + ste.getLineNumber();
}
public Trace(Sampler sampler, Thread thread) {
this(sampler, thread.getName());
}
public Trace(Sampler sampler, String name) { public Trace(Sampler sampler, String name) {
this.sampler = sampler; this.sampler = sampler;
id = idCounter++; id = idCounter++;
@ -36,15 +26,15 @@ public class Trace {
} }
private int ownSampleRuns() { private int ownSampleRuns() {
return samples.values().stream().mapToInt(i -> i).sum(); return Arrays.stream(samples).sum();
} }
private boolean filtered() { private boolean filtered() {
return (samples.getOrDefault(Thread.State.RUNNABLE, 0) + samples.getOrDefault(Thread.State.BLOCKED, 0)) / (double) sampler.getSampleRuns() < Sampler.FILTER; return (samples[1] + samples[2]) / (double) sampler.getSampleRuns() < Sampler.FILTER;
} }
public void add(Thread.State state, Trace predecessor) { public void add(Thread.State state, Trace predecessor) {
samples.compute(state, (s, sample) -> sample == null ? 1 : sample + 1); samples[state.ordinal()] += 1;
if (predecessor != null) if (predecessor != null)
predecessors.compute(predecessor, (pre, sample) -> sample == null ? 1 : sample + 1); predecessors.compute(predecessor, (pre, sample) -> sample == null ? 1 : sample + 1);
} }
@ -57,9 +47,9 @@ public class Trace {
if (filtered()) if (filtered())
return; return;
int waiting = samples.getOrDefault(Thread.State.WAITING, 0) + samples.getOrDefault(Thread.State.TIMED_WAITING, 0) + samples.getOrDefault(Thread.State.TERMINATED, 0); int waiting = samples[3] + samples[4] + samples[5];
int runnable = samples.getOrDefault(Thread.State.RUNNABLE, 0) + samples.getOrDefault(Thread.State.NEW, 0); int runnable = samples[1] + samples[0];
int blocked = samples.getOrDefault(Thread.State.BLOCKED, 0); int blocked = samples[2];
int total = waiting + runnable + blocked; int total = waiting + runnable + blocked;
int r = (255 * blocked + 192 * waiting) / total; int r = (255 * blocked + 192 * waiting) / total;
@ -75,7 +65,7 @@ public class Trace {
if (entry.getKey().filtered() || entry.getValue() / (double)sampler.getSampleRuns() < Sampler.FILTER) if (entry.getKey().filtered() || entry.getValue() / (double)sampler.getSampleRuns() < Sampler.FILTER)
continue; continue;
writer.append(String.valueOf(entry.getKey().id)).append(" -> ").append(String.valueOf(id)).append(" [label=\"").append(percentage(entry.getValue())).append("%\"];\n"); writer.append(String.valueOf(entry.getKey().id)).append(" -> ").append(String.valueOf(id)).append(" [label=\"").append(percentage(entry.getValue())).append("%\",weight=").append(String.valueOf(entry.getValue())).append("];\n");
} }
} }
} }