mirror of
https://github.com/EngineHub/WorldGuard.git
synced 2024-12-26 02:57:42 +01:00
Add CPU profiling with WarmRoast "lite."
This commit is contained in:
parent
477f1188df
commit
547e89b85d
@ -20,6 +20,11 @@
|
||||
package com.sk89q.worldguard.bukkit.commands;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.util.paste.EngineHubPaste;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.command.BlockCommandSender;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@ -27,12 +32,17 @@
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.net.URL;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Command-related utility methods.
|
||||
*/
|
||||
public final class CommandUtils {
|
||||
|
||||
private static final Logger log = Logger.getLogger(CommandUtils.class.getCanonicalName());
|
||||
|
||||
private CommandUtils() {
|
||||
}
|
||||
|
||||
@ -153,4 +163,34 @@ public Object apply(@Nullable String s) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit data to a pastebin service and inform the sender of
|
||||
* success or failure.
|
||||
*
|
||||
* @param plugin The plugin
|
||||
* @param sender The sender
|
||||
* @param content The content
|
||||
* @param successMessage The message, formatted with {@link String#format(String, Object...)} on success
|
||||
*/
|
||||
public static void pastebin(WorldGuardPlugin plugin, final CommandSender sender, String content, final String successMessage) {
|
||||
ListenableFuture<URL> future = new EngineHubPaste().paste(content);
|
||||
|
||||
AsyncCommandHelper.wrap(future, plugin, sender)
|
||||
.registerWithSupervisor("Submitting content to a pastebin service...")
|
||||
.sendMessageAfterDelay("(Please wait... sending output to pastebin...)");
|
||||
|
||||
Futures.addCallback(future, new FutureCallback<URL>() {
|
||||
@Override
|
||||
public void onSuccess(URL url) {
|
||||
sender.sendMessage(ChatColor.YELLOW + String.format(successMessage, url));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable throwable) {
|
||||
log.log(Level.WARNING, "Failed to submit pastebin", throwable);
|
||||
sender.sendMessage(ChatColor.RED + "Failed to submit to a pastebin. Please see console for the error.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,15 +19,21 @@
|
||||
|
||||
package com.sk89q.worldguard.bukkit.commands;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.io.Files;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
import com.sk89q.minecraft.util.commands.*;
|
||||
import com.sk89q.worldguard.bukkit.ConfigurationManager;
|
||||
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
|
||||
import com.sk89q.worldguard.bukkit.util.logging.LoggerToChatHandler;
|
||||
import com.sk89q.worldguard.bukkit.util.report.*;
|
||||
import com.sk89q.worldguard.util.paste.EngineHubPaste;
|
||||
import com.sk89q.worldguard.util.profiler.SamplerBuilder;
|
||||
import com.sk89q.worldguard.util.profiler.SamplerBuilder.Sampler;
|
||||
import com.sk89q.worldguard.util.profiler.ThreadIdFilter;
|
||||
import com.sk89q.worldguard.util.profiler.ThreadNameFilter;
|
||||
import com.sk89q.worldguard.util.report.ReportList;
|
||||
import com.sk89q.worldguard.util.report.SystemInfoReport;
|
||||
import com.sk89q.worldguard.util.task.Task;
|
||||
@ -38,12 +44,14 @@
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.lang.management.ThreadInfo;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@ -52,6 +60,8 @@ public class WorldGuardCommands {
|
||||
private static final Logger log = Logger.getLogger(WorldGuardCommands.class.getCanonicalName());
|
||||
|
||||
private final WorldGuardPlugin plugin;
|
||||
@Nullable
|
||||
private Sampler activeSampler;
|
||||
|
||||
public WorldGuardCommands(WorldGuardPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
@ -128,23 +138,111 @@ public void report(CommandContext args, final CommandSender sender) throws Comma
|
||||
|
||||
if (args.hasFlag('p')) {
|
||||
plugin.checkPermission(sender, "worldguard.report.pastebin");
|
||||
|
||||
sender.sendMessage(ChatColor.YELLOW + "Now uploading to Pastebin...");
|
||||
CommandUtils.pastebin(plugin, sender, result, "WorldGuard report: %s.report");
|
||||
}
|
||||
}
|
||||
|
||||
Futures.addCallback(new EngineHubPaste().paste(result), new FutureCallback<URL>() {
|
||||
@Override
|
||||
public void onSuccess(URL url) {
|
||||
sender.sendMessage(ChatColor.YELLOW + "WorldGuard report: " + url + ".report");
|
||||
}
|
||||
@Command(aliases = {"profile"}, usage = "[<minutes>]",
|
||||
desc = "Profile the CPU usage of the server", min = 0, max = 1,
|
||||
flags = "t:p")
|
||||
@CommandPermissions("worldguard.profile")
|
||||
public void profile(final CommandContext args, final CommandSender sender) throws CommandException {
|
||||
Predicate<ThreadInfo> threadFilter;
|
||||
String threadName = args.getFlag('t');
|
||||
final boolean pastebin;
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable throwable) {
|
||||
log.log(Level.WARNING, "Failed to submit pastebin", throwable);
|
||||
sender.sendMessage(ChatColor.RED + "The WorldGuard report could not be saved to a pastebin service. Please see console for the error.");
|
||||
}
|
||||
});
|
||||
if (args.hasFlag('p')) {
|
||||
plugin.checkPermission(sender, "worldguard.report.pastebin");
|
||||
pastebin = true;
|
||||
} else {
|
||||
pastebin = false;
|
||||
}
|
||||
|
||||
if (threadName == null) {
|
||||
threadFilter = new ThreadIdFilter(Thread.currentThread().getId());
|
||||
} else if (threadName.equals("*")) {
|
||||
threadFilter = Predicates.alwaysTrue();
|
||||
} else {
|
||||
threadFilter = new ThreadNameFilter(threadName);
|
||||
}
|
||||
|
||||
int minutes;
|
||||
if (args.argsLength() == 0) {
|
||||
minutes = 5;
|
||||
} else {
|
||||
minutes = args.getInteger(0);
|
||||
if (minutes < 1) {
|
||||
throw new CommandException("You must run the profile for at least 1 minute.");
|
||||
} else if (minutes > 10) {
|
||||
throw new CommandException("You can profile for, at maximum, 10 minutes.");
|
||||
}
|
||||
}
|
||||
|
||||
Sampler sampler;
|
||||
|
||||
synchronized (this) {
|
||||
if (activeSampler != null) {
|
||||
throw new CommandException("A profile is currently in progress! Please use /wg stopprofile to stop the current profile.");
|
||||
}
|
||||
|
||||
SamplerBuilder builder = new SamplerBuilder();
|
||||
builder.setThreadFilter(threadFilter);
|
||||
builder.setRunTime(minutes, TimeUnit.MINUTES);
|
||||
sampler = activeSampler = builder.start();
|
||||
}
|
||||
|
||||
AsyncCommandHelper.wrap(sampler.getFuture(), plugin, sender)
|
||||
.formatUsing(minutes)
|
||||
.registerWithSupervisor("Running CPU profiler for %d minute(s)...")
|
||||
.sendMessageAfterDelay("(Please wait... profiling for %d minute(s)...)")
|
||||
.thenTellErrorsOnly("CPU profiling failed.");
|
||||
|
||||
sampler.getFuture().addListener(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (WorldGuardCommands.this) {
|
||||
activeSampler = null;
|
||||
}
|
||||
}
|
||||
}, MoreExecutors.sameThreadExecutor());
|
||||
|
||||
Futures.addCallback(sampler.getFuture(), new FutureCallback<Sampler>() {
|
||||
@Override
|
||||
public void onSuccess(Sampler result) {
|
||||
String output = result.toString();
|
||||
|
||||
try {
|
||||
File dest = new File(plugin.getDataFolder(), "profile.txt");
|
||||
Files.write(output, dest, Charset.forName("UTF-8"));
|
||||
sender.sendMessage(ChatColor.YELLOW + "CPU profiling data written to " + dest.getAbsolutePath());
|
||||
} catch (IOException e) {
|
||||
sender.sendMessage(ChatColor.RED + "Failed to write CPU profiling data: " + e.getMessage());
|
||||
}
|
||||
|
||||
if (pastebin) {
|
||||
CommandUtils.pastebin(plugin, sender, output, "Profile result: %s.profile");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable throwable) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Command(aliases = {"stopprofile"}, usage = "",desc = "Stop a running profile", min = 0, max = 0)
|
||||
@CommandPermissions("worldguard.profile")
|
||||
public void stopProfile(CommandContext args, final CommandSender sender) throws CommandException {
|
||||
synchronized (this) {
|
||||
if (activeSampler == null) {
|
||||
throw new CommandException("No CPU profile is currently running.");
|
||||
}
|
||||
|
||||
activeSampler.cancel();
|
||||
activeSampler = null;
|
||||
}
|
||||
|
||||
sender.sendMessage("The running CPU profile has been stopped.");
|
||||
}
|
||||
|
||||
@Command(aliases = {"flushstates", "clearstates"},
|
||||
|
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.util.profiler;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.SettableFuture;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.ThreadInfo;
|
||||
import java.lang.management.ThreadMXBean;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class SamplerBuilder {
|
||||
|
||||
private static final Timer timer = new Timer("WorldGuard Sampler", true);
|
||||
private int interval = 100;
|
||||
private long runTime = TimeUnit.MINUTES.toMillis(5);
|
||||
private Predicate<ThreadInfo> threadFilter = Predicates.alwaysTrue();
|
||||
|
||||
public int getInterval() {
|
||||
return interval;
|
||||
}
|
||||
|
||||
public void setInterval(int interval) {
|
||||
checkArgument(interval >= 10, "interval >= 10");
|
||||
this.interval = interval;
|
||||
}
|
||||
|
||||
public Predicate<ThreadInfo> getThreadFilter() {
|
||||
return threadFilter;
|
||||
}
|
||||
|
||||
public void setThreadFilter(Predicate<ThreadInfo> threadFilter) {
|
||||
checkNotNull(threadFilter, "threadFilter");
|
||||
this.threadFilter = threadFilter;
|
||||
}
|
||||
|
||||
public long getRunTime(TimeUnit timeUnit) {
|
||||
return timeUnit.convert(runTime, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public void setRunTime(long time, TimeUnit timeUnit) {
|
||||
checkArgument(time > 0, "time > 0");
|
||||
this.runTime = timeUnit.toMillis(time);
|
||||
}
|
||||
|
||||
public Sampler start() {
|
||||
Sampler sampler = new Sampler(interval, threadFilter, System.currentTimeMillis() + runTime);
|
||||
timer.scheduleAtFixedRate(sampler, 0, interval);
|
||||
return sampler;
|
||||
}
|
||||
|
||||
public static class Sampler extends TimerTask {
|
||||
private final int interval;
|
||||
private final Predicate<ThreadInfo> threadFilter;
|
||||
private final long endTime;
|
||||
|
||||
private final SortedMap<String, StackNode> nodes = new TreeMap<String, StackNode>();
|
||||
private final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
|
||||
private final SettableFuture<Sampler> future = SettableFuture.create();
|
||||
|
||||
private Sampler(int interval, Predicate<ThreadInfo> threadFilter, long endTime) {
|
||||
this.interval = interval;
|
||||
this.threadFilter = threadFilter;
|
||||
this.endTime = endTime;
|
||||
}
|
||||
|
||||
public ListenableFuture<Sampler> getFuture() {
|
||||
return future;
|
||||
}
|
||||
|
||||
private Map<String, StackNode> getData() {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private StackNode getNode(String name) {
|
||||
StackNode node = nodes.get(name);
|
||||
if (node == null) {
|
||||
node = new StackNode(name);
|
||||
nodes.put(name, node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void run() {
|
||||
try {
|
||||
if (endTime <= System.currentTimeMillis()) {
|
||||
future.set(this);
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
ThreadInfo[] threadDumps = threadBean.dumpAllThreads(false, false);
|
||||
for (ThreadInfo threadInfo : threadDumps) {
|
||||
String threadName = threadInfo.getThreadName();
|
||||
StackTraceElement[] stack = threadInfo.getStackTrace();
|
||||
|
||||
if (threadName != null && stack != null && threadFilter.apply(threadInfo)) {
|
||||
StackNode node = getNode(threadName);
|
||||
node.log(stack, interval);
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
future.setException(t);
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (Map.Entry<String, StackNode> entry : getData().entrySet()) {
|
||||
builder.append(entry.getKey());
|
||||
builder.append(" ");
|
||||
builder.append(entry.getValue().getTotalTime()).append("ms");
|
||||
builder.append("\n");
|
||||
entry.getValue().writeString(builder, 1);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
121
src/main/java/com/sk89q/worldguard/util/profiler/StackNode.java
Normal file
121
src/main/java/com/sk89q/worldguard/util/profiler/StackNode.java
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.util.profiler;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class StackNode implements Comparable<StackNode> {
|
||||
|
||||
private final String name;
|
||||
private final Map<String, StackNode> children = Maps.newHashMap();
|
||||
private long totalTime;
|
||||
|
||||
public StackNode(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Collection<StackNode> getChildren() {
|
||||
List<StackNode> list = Lists.newArrayList(children.values());
|
||||
Collections.sort(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
public StackNode getChild(String name) {
|
||||
StackNode child = children.get(name);
|
||||
if (child == null) {
|
||||
child = new StackNode(name);
|
||||
children.put(name, child);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
public StackNode getChild(String className, String methodName) {
|
||||
StackTraceNode node = new StackTraceNode(className, methodName);
|
||||
StackNode child = children.get(node.getName());
|
||||
if (child == null) {
|
||||
child = node;
|
||||
children.put(node.getName(), node);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
public long getTotalTime() {
|
||||
return totalTime;
|
||||
}
|
||||
|
||||
public void log(long time) {
|
||||
totalTime += time;
|
||||
}
|
||||
|
||||
private void log(StackTraceElement[] elements, int skip, long time) {
|
||||
log(time);
|
||||
|
||||
if (elements.length - skip == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
StackTraceElement bottom = elements[elements.length - (skip + 1)];
|
||||
getChild(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());
|
||||
}
|
||||
|
||||
void writeString(StringBuilder builder, int indent) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (int i = 0; i < indent; i++) {
|
||||
b.append(" ");
|
||||
}
|
||||
String padding = b.toString();
|
||||
|
||||
for (StackNode child : getChildren()) {
|
||||
builder.append(padding).append(child.getName());
|
||||
builder.append(" ");
|
||||
builder.append(child.getTotalTime()).append("ms");
|
||||
builder.append("\n");
|
||||
child.writeString(builder, indent + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
writeString(builder, 0);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.util.profiler;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class StackTraceNode extends StackNode {
|
||||
|
||||
private final String className;
|
||||
private final String methodName;
|
||||
|
||||
public StackTraceNode(String className, String methodName) {
|
||||
super(className + "." + methodName + "()");
|
||||
this.className = className;
|
||||
this.methodName = methodName;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
public String getMethodName() {
|
||||
return methodName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(StackNode o) {
|
||||
if (getTotalTime() == o.getTotalTime()) {
|
||||
return 0;
|
||||
} else if (getTotalTime()> o.getTotalTime()) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.util.profiler;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import java.lang.management.ThreadInfo;
|
||||
|
||||
public class ThreadIdFilter implements Predicate<ThreadInfo> {
|
||||
|
||||
private final long id;
|
||||
|
||||
public ThreadIdFilter(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(ThreadInfo threadInfo) {
|
||||
return threadInfo.getThreadId() == id;
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* WorldGuard, a suite of tools for Minecraft
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldGuard team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldguard.util.profiler;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
||||
import java.lang.management.ThreadInfo;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class ThreadNameFilter implements Predicate<ThreadInfo> {
|
||||
|
||||
private final String name;
|
||||
|
||||
public ThreadNameFilter(String name) {
|
||||
checkNotNull(name, "name");
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(ThreadInfo threadInfo) {
|
||||
return threadInfo.getThreadName().equalsIgnoreCase(name);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user