aboutsummaryrefslogtreecommitdiff
path: root/common/src/main/java/com/sk89q/warmroast
diff options
context:
space:
mode:
Diffstat (limited to 'common/src/main/java/com/sk89q/warmroast')
-rw-r--r--common/src/main/java/com/sk89q/warmroast/Sampler.java200
-rw-r--r--common/src/main/java/com/sk89q/warmroast/StackNode.java140
-rw-r--r--common/src/main/java/com/sk89q/warmroast/StackTraceNode.java69
-rw-r--r--common/src/main/java/com/sk89q/warmroast/ThreadDumper.java72
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);
- }
- }
-
-}