Improve performance + Flatten recursion
Dieser Commit ist enthalten in:
Ursprung
230209436d
Commit
cf76202775
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren