diff options
Diffstat (limited to 'common/src/main/java/com')
4 files changed, 0 insertions, 481 deletions
diff --git a/common/src/main/java/com/sk89q/warmroast/Sampler.java b/common/src/main/java/com/sk89q/warmroast/Sampler.java deleted file mode 100644 index a141f82..0000000 --- a/common/src/main/java/com/sk89q/warmroast/Sampler.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * WarmRoast - * Copyright (C) 2013 Albert Pham <http://www.sk89q.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -package com.sk89q.warmroast; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; - -import java.lang.management.ManagementFactory; -import java.lang.management.ThreadInfo; -import java.lang.management.ThreadMXBean; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; - -/** - * Main sampler class. - */ -public class Sampler extends TimerTask { - - /** The thread management interface for the current JVM */ - private final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean(); - - /** A map of root stack nodes for each thread with sampling data */ - private final Map<String, StackNode> threadData = new HashMap<>(); - - /** A set of recorded thread info that's yet to be inserted into the node structure */ - private final Set<QueuedThreadInfo> pendingThreadData = Collections.synchronizedSet(Collections.newSetFromMap(new IdentityHashMap<>())); - - /** The worker pool for inserting stack nodes */ - private ExecutorService workerPool; - /** The lock object */ - private final Object[] lock = new Object[0]; - /** A future to encapsulation the completion of this sampler instance */ - private final CompletableFuture<Sampler> future = new CompletableFuture<>(); - - /** The interval to wait between sampling, in milliseconds */ - private final int interval; - /** The instance used to generate thread information for use in sampling */ - private final ThreadDumper threadDumper; - /** The time when sampling first began */ - private long startTime = -1; - /** The unix timestamp (in millis) when this sampler should automatically complete.*/ - private final long endTime; // -1 for nothing - - public Sampler(int interval, ThreadDumper threadDumper, long endTime) { - this.interval = interval; - this.threadDumper = threadDumper; - this.endTime = endTime; - } - - /** - * Starts the sampler. - * - * @param samplingThread the timer to schedule the sampling on - * @param workerPool the worker pool - */ - public void start(Timer samplingThread, ExecutorService workerPool) { - this.workerPool = workerPool; - samplingThread.scheduleAtFixedRate(this, 0, this.interval); - this.startTime = System.currentTimeMillis(); - } - - private void insertData(QueuedThreadInfo data) { - synchronized (this.lock) { - try { - StackNode node = this.threadData.computeIfAbsent(data.threadName, StackNode::new); - node.log(data.stack, Sampler.this.interval); - this.pendingThreadData.remove(data); - } catch (Exception e) { - e.printStackTrace(); - // we need to remove the pending data even if the insert failed - this.pendingThreadData.remove(data); - } - } - } - - /** - * Gets the sampling data recorded by this instance. - * - * @return the data - */ - public Map<String, StackNode> getData() { - if (this.pendingThreadData.isEmpty()) { - return this.threadData; - } - - // wait for all pending data to be inserted - while (true) { - synchronized (this.lock) { - if (this.pendingThreadData.isEmpty()) { - return this.threadData; - } - } - } - } - - public long getStartTime() { - if (this.startTime == -1) { - throw new IllegalStateException("Not yet started"); - } - return this.startTime; - } - - public long getEndTime() { - return this.endTime; - } - - public CompletableFuture<Sampler> getFuture() { - return this.future; - } - - @Override - public void run() { - try { - if (this.endTime != -1 && this.endTime <= System.currentTimeMillis()) { - this.future.complete(this); - cancel(); - return; - } - - ThreadInfo[] threadDumps = this.threadDumper.dumpThreads(this.threadBean); - for (ThreadInfo threadInfo : threadDumps) { - String threadName = threadInfo.getThreadName(); - StackTraceElement[] stack = threadInfo.getStackTrace(); - - if (threadName == null || stack == null) { - continue; - } - - QueuedThreadInfo queuedData = new QueuedThreadInfo(threadName, stack); - this.pendingThreadData.add(queuedData); - this.workerPool.execute(queuedData); - } - } catch (Throwable t) { - this.future.completeExceptionally(t); - cancel(); - } - } - - public JsonObject formOutput() { - JsonObject out = new JsonObject(); - - JsonArray threads = new JsonArray(); - - List<Map.Entry<String, StackNode>> data = new ArrayList<>(getData().entrySet()); - data.sort(Map.Entry.comparingByKey()); - - for (Map.Entry<String, StackNode> entry : data) { - JsonObject o = new JsonObject(); - o.addProperty("threadName", entry.getKey()); - o.addProperty("totalTime", entry.getValue().getTotalTime()); - o.add("rootNode", entry.getValue().serialize()); - - threads.add(o); - } - out.add("threads", threads); - - return out; - } - - private final class QueuedThreadInfo implements Runnable { - private final String threadName; - private final StackTraceElement[] stack; - - private QueuedThreadInfo(String threadName, StackTraceElement[] stack) { - this.threadName = threadName; - this.stack = stack; - } - - @Override - public void run() { - insertData(this); - } - } - -} diff --git a/common/src/main/java/com/sk89q/warmroast/StackNode.java b/common/src/main/java/com/sk89q/warmroast/StackNode.java deleted file mode 100644 index 8fd0661..0000000 --- a/common/src/main/java/com/sk89q/warmroast/StackNode.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * WarmRoast - * Copyright (C) 2013 Albert Pham <http://www.sk89q.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -package com.sk89q.warmroast; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Represents a node in the overall sampling stack. - * - * <p>The base implementation of this class is only used for the root of node structures. The - * {@link StackTraceNode} class is used for representing method calls in the structure.</p> - */ -public class StackNode implements Comparable<StackNode> { - - private static final int MAX_STACK_DEPTH = 300; - - /** - * The name of this node - */ - private final String name; - - /** - * A map of this nodes children - */ - private final Map<String, StackNode> children = new HashMap<>(); - - /** - * The accumulated sample time for this node - */ - private long totalTime = 0; - - public StackNode(String name) { - this.name = name; - } - - public String getName() { - return this.name; - } - - public Collection<StackNode> getChildren() { - if (this.children.isEmpty()) { - return Collections.emptyList(); - } - - List<StackNode> list = new ArrayList<>(this.children.values()); - list.sort(null); - return list; - } - - private StackNode resolveChild(String name) { - return this.children.computeIfAbsent(name, StackNode::new); - } - - private StackNode resolveChild(String className, String methodName) { - return this.children.computeIfAbsent(StackTraceNode.formName(className, methodName), name -> new StackTraceNode(className, methodName)); - } - - public long getTotalTime() { - return this.totalTime; - } - - public void accumulateTime(long time) { - this.totalTime += time; - } - - private void log(StackTraceElement[] elements, int skip, long time) { - accumulateTime(time); - - if (skip >= MAX_STACK_DEPTH) { - return; - } - - if (elements.length - skip == 0) { - return; - } - - StackTraceElement bottom = elements[elements.length - (skip + 1)]; - resolveChild(bottom.getClassName(), bottom.getMethodName()).log(elements, skip + 1, time); - } - - public void log(StackTraceElement[] elements, long time) { - log(elements, 0, time); - } - - @Override - public int compareTo(StackNode o) { - return getName().compareTo(o.getName()); - } - - public JsonObject serialize() { - JsonObject ret = new JsonObject(); - - // append metadata about this node - appendMetadata(ret); - - // include the total time recorded for this node - ret.addProperty("totalTime", getTotalTime()); - - // append child nodes, if any are present - Collection<StackNode> childNodes = getChildren(); - if (!childNodes.isEmpty()) { - JsonArray children = new JsonArray(); - for (StackNode child : childNodes) { - children.add(child.serialize()); - } - ret.add("children", children); - } - - return ret; - } - - protected void appendMetadata(JsonObject obj) { - obj.addProperty("name", getName()); - } - -} diff --git a/common/src/main/java/com/sk89q/warmroast/StackTraceNode.java b/common/src/main/java/com/sk89q/warmroast/StackTraceNode.java deleted file mode 100644 index 016d700..0000000 --- a/common/src/main/java/com/sk89q/warmroast/StackTraceNode.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * WarmRoast - * Copyright (C) 2013 Albert Pham <http://www.sk89q.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -package com.sk89q.warmroast; - -import com.google.gson.JsonObject; - -/** - * Represents a {@link StackNode node} for a method call. - */ -public class StackTraceNode extends StackNode { - - /** - * Forms the {@link StackNode#getName()} for a {@link StackTraceNode}. - * - * @param className the name of the class - * @param methodName the name of the method - * @return the name - */ - static String formName(String className, String methodName) { - return className + "." + methodName + "()"; - } - - /** The name of the class */ - private final String className; - /** The name of the method */ - private final String methodName; - - public StackTraceNode(String className, String methodName) { - super(formName(className, methodName)); - this.className = className; - this.methodName = methodName; - } - - public String getClassName() { - return className; - } - - public String getMethodName() { - return methodName; - } - - @Override - protected void appendMetadata(JsonObject obj) { - obj.addProperty("className", className); - obj.addProperty("methodName", methodName); - } - - @Override - public int compareTo(StackNode that) { - return Long.compare(that.getTotalTime(), this.getTotalTime()); - } - -} diff --git a/common/src/main/java/com/sk89q/warmroast/ThreadDumper.java b/common/src/main/java/com/sk89q/warmroast/ThreadDumper.java deleted file mode 100644 index 6c25daf..0000000 --- a/common/src/main/java/com/sk89q/warmroast/ThreadDumper.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * WarmRoast - * Copyright (C) 2013 Albert Pham <http://www.sk89q.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -package com.sk89q.warmroast; - -import java.lang.management.ThreadInfo; -import java.lang.management.ThreadMXBean; - -/** - * Uses the {@link ThreadMXBean} to generate {@link ThreadInfo} instances for the threads being - * sampled. - */ -@FunctionalInterface -public interface ThreadDumper { - - /** - * Generates {@link ThreadInfo} data for the sampled threads. - * - * @param threadBean the thread bean instance to obtain the data from - * @return an array of generated thread info instances - */ - ThreadInfo[] dumpThreads(ThreadMXBean threadBean); - - /** - * Implementation of {@link ThreadDumper} that generates data for all threads. - */ - final class All implements ThreadDumper { - @Override - public ThreadInfo[] dumpThreads(ThreadMXBean threadBean) { - return threadBean.dumpAllThreads(false, false); - } - } - - /** - * Implementation of {@link ThreadDumper} that generates data for a specific set of threads. - */ - final class Specific implements ThreadDumper { - private final long[] ids; - - public Specific(long[] ids) { - this.ids = ids; - } - - public Specific(String name) { - this.ids = Thread.getAllStackTraces().keySet().stream() - .filter(t -> t.getName().equalsIgnoreCase(name)) - .mapToLong(Thread::getId) - .toArray(); - } - - @Override - public ThreadInfo[] dumpThreads(ThreadMXBean threadBean) { - return threadBean.getThreadInfo(this.ids, Integer.MAX_VALUE); - } - } - -} |