From 468d45b7613dfd177a40cee0ff097728954c16e2 Mon Sep 17 00:00:00 2001 From: Tahg Date: Mon, 16 Jan 2012 15:03:41 -0500 Subject: Updated timing code for new event system --- .../bukkit/command/defaults/TimingsCommand.java | 36 ++++++++-- src/main/java/org/bukkit/event/HandlerList.java | 18 +++++ src/main/java/org/bukkit/plugin/Plugin.java | 6 -- src/main/java/org/bukkit/plugin/PluginManager.java | 7 ++ .../org/bukkit/plugin/SimplePluginManager.java | 35 ++++++++-- .../org/bukkit/plugin/TimedRegisteredListener.java | 77 ++++++++++++++++++++++ .../java/org/bukkit/plugin/java/JavaPlugin.java | 13 ---- .../org/bukkit/plugin/java/JavaPluginLoader.java | 10 ++- 8 files changed, 169 insertions(+), 33 deletions(-) create mode 100644 src/main/java/org/bukkit/plugin/TimedRegisteredListener.java (limited to 'src') diff --git a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java index 6b725797..8d65c13a 100644 --- a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java +++ b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java @@ -4,11 +4,16 @@ import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.RegisteredListener; +import org.bukkit.plugin.TimedRegisteredListener; import java.io.File; import java.io.IOException; import java.io.PrintStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; public class TimingsCommand extends Command { public TimingsCommand(String name) { @@ -22,11 +27,21 @@ public class TimingsCommand extends Command { public boolean execute(CommandSender sender, String currentAlias, String[] args) { if (!testPermission(sender)) return true; if (args.length != 1) return false; + if (!sender.getServer().getPluginManager().useTimings()) { + sender.sendMessage("Please enable timings by setting \"settings.plugin-profiling\" to true in bukkit.yml"); + return true; + } boolean seperate = "seperate".equals(args[0]); if ("reset".equals(args[0])) { - for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { - plugin.resetTimings(); + for (HandlerList handlerList : HandlerList.getHandlerLists()) { + for (RegisteredListener[] listeners : handlerList.getRegisteredListeners()) { + for (RegisteredListener listener : listeners) { + if (listener instanceof TimedRegisteredListener) { + ((TimedRegisteredListener)listener).reset(); + } + } + } } sender.sendMessage("Timings reset"); } else if ("merged".equals(args[0]) || seperate) { @@ -53,11 +68,18 @@ public class TimingsCommand extends Command { fileTimings.println("Plugin " + pluginIdx); } else fileTimings.println(plugin.getDescription().getFullName()); - for (Event.Type type : Event.Type.values()) { - long time = plugin.getTiming(type); - totalTime += time; - if (time > 0) { - fileTimings.println(" " + type.name() + " " + time); + for (RegisteredListener listener : HandlerList.getRegisteredListeners(plugin)) { + if (listener instanceof TimedRegisteredListener) { + TimedRegisteredListener trl = (TimedRegisteredListener) listener; + long time = trl.getTotalTime(); + int count = trl.getCount(); + if (count == 0) continue; + long avg = time / count; + totalTime += time; + Event event = trl.getEvent(); + if (count > 0 && event != null) { + fileTimings.println(" " + event.getClass().getSimpleName() + (trl.hasMultiple() ? " (and others)" : "") + " Time: " + time + " Count: " + count + " Avg: " + avg); + } } } fileTimings.println(" Total time " + totalTime + " (" + totalTime / 1000000000 + "s)"); diff --git a/src/main/java/org/bukkit/event/HandlerList.java b/src/main/java/org/bukkit/event/HandlerList.java index 601c3b63..c2159402 100644 --- a/src/main/java/org/bukkit/event/HandlerList.java +++ b/src/main/java/org/bukkit/event/HandlerList.java @@ -132,4 +132,22 @@ public class HandlerList { public RegisteredListener[][] getRegisteredListeners() { return handlers; } + + public static ArrayList getRegisteredListeners(Plugin plugin) { + ArrayList listeners = new ArrayList(); + for (HandlerList h : alllists) { + for (List list : h.handlerslots.values()) { + for (RegisteredListener listener : list) { + if (listener.getPlugin().equals(plugin)) { + listeners.add(listener); + } + } + } + } + return listeners; + } + + public static ArrayList getHandlerLists() { + return (ArrayList) alllists.clone(); + } } diff --git a/src/main/java/org/bukkit/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/Plugin.java index 80cb0acb..4cba6f76 100644 --- a/src/main/java/org/bukkit/plugin/Plugin.java +++ b/src/main/java/org/bukkit/plugin/Plugin.java @@ -158,10 +158,4 @@ public interface Plugin extends CommandExecutor { * @return Logger associated with this server */ public Logger getLogger(); - - public long getTiming(Event.Type type); - - public void incTiming(Event.Type type, long delta); - - public void resetTimings(); } diff --git a/src/main/java/org/bukkit/plugin/PluginManager.java b/src/main/java/org/bukkit/plugin/PluginManager.java index c2930e28..3fbb187f 100644 --- a/src/main/java/org/bukkit/plugin/PluginManager.java +++ b/src/main/java/org/bukkit/plugin/PluginManager.java @@ -276,4 +276,11 @@ public interface PluginManager { * @return Set containing all current registered permissions */ public Set getPermissions(); + + /** + * Returns whether or not timing code should be used for event calls + * + * @return True if event timings are to be used + */ + public boolean useTimings(); } diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java index 63cf619d..b6fbe2eb 100644 --- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java @@ -33,6 +33,7 @@ public final class SimplePluginManager implements PluginManager { private final Map> defaultPerms = new LinkedHashMap>(); private final Map> permSubs = new HashMap>(); private final Map> defSubs = new HashMap>(); + private boolean useTimings = false; public SimplePluginManager(Server instance, SimpleCommandMap commandMap) { server = instance; @@ -323,9 +324,7 @@ public final class SimplePluginManager implements PluginManager { } try { - long start = System.nanoTime(); registration.callEvent(event); - registration.getPlugin().incTiming(event.getType(), System.nanoTime() - start); } catch (AuthorNagException ex) { Plugin plugin = registration.getPlugin(); @@ -393,7 +392,11 @@ public final class SimplePluginManager implements PluginManager { throw new IllegalPluginAccessException("Plugin attempted to register " + type + " while not enabled"); } - getEventListeners(type.getEventClass()).register(new RegisteredListener(listener, plugin.getPluginLoader().createExecutor(type, listener), priority.getNewPriority(), plugin)); + if (useTimings) { + getEventListeners(type.getEventClass()).register(new TimedRegisteredListener(listener, plugin.getPluginLoader().createExecutor(type, listener), priority.getNewPriority(), plugin)); + } else { + getEventListeners(type.getEventClass()).register(new RegisteredListener(listener, plugin.getPluginLoader().createExecutor(type, listener), priority.getNewPriority(), plugin)); + } } /** @@ -422,7 +425,12 @@ public final class SimplePluginManager implements PluginManager { throw new IllegalPluginAccessException("Plugin attempted to register " + type + " while not enabled"); } - getEventListeners(type.getEventClass()).register(new RegisteredListener(listener, executor, priority.getNewPriority(), plugin)); + if (useTimings) { + getEventListeners(type.getEventClass()).register(new TimedRegisteredListener(listener, executor, priority.getNewPriority(), plugin)); + } + else { + getEventListeners(type.getEventClass()).register(new RegisteredListener(listener, executor, priority.getNewPriority(), plugin)); + } } public void registerEvents(Listener listener, Plugin plugin) { @@ -445,7 +453,11 @@ public final class SimplePluginManager implements PluginManager { throw new IllegalPluginAccessException("Plugin attempted to register " + event + " while not enabled"); } - getEventListeners(event).register(new RegisteredListener(listener, executor, priority, plugin)); + if (useTimings) { + getEventListeners(event).register(new TimedRegisteredListener(listener, executor, priority, plugin)); + } else { + getEventListeners(event).register(new RegisteredListener(listener, executor, priority, plugin)); + } } /** @@ -606,4 +618,17 @@ public final class SimplePluginManager implements PluginManager { public Set getPermissions() { return new HashSet(permissions.values()); } + + public boolean useTimings() { + return useTimings; + } + + /** + * Sets whether or not per event timing code should be used + * + * @param use True if per event timing code should be used + */ + public void useTimings(boolean use) { + useTimings = use; + } } diff --git a/src/main/java/org/bukkit/plugin/TimedRegisteredListener.java b/src/main/java/org/bukkit/plugin/TimedRegisteredListener.java new file mode 100644 index 00000000..e2dffdae --- /dev/null +++ b/src/main/java/org/bukkit/plugin/TimedRegisteredListener.java @@ -0,0 +1,77 @@ +package org.bukkit.plugin; + +import org.bukkit.event.Event; +import org.bukkit.event.EventException; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; + +/** + * Extends RegisteredListener to include timing information + */ +public class TimedRegisteredListener extends RegisteredListener { + private int count; + private long totalTime; + private Event event; + private boolean multiple = false; + + public TimedRegisteredListener(final Listener pluginListener, final EventExecutor eventExecutor, final EventPriority eventPriority, final Plugin registeredPlugin) { + super(pluginListener, eventExecutor, eventPriority, registeredPlugin); + } + + public void callEvent(Event event) throws EventException { + count++; + if (this.event == null) { + this.event = event; + } + else if (!this.event.getClass().equals(event.getClass())) { + multiple = true; + } + long start = System.nanoTime(); + super.callEvent(event); + totalTime += System.nanoTime() - start; + } + + /** + * Resets the call count and total time for this listener + */ + public void reset() { + count = 0; + totalTime = 0; + } + + /** + * Gets the total times this listener has been called + * + * @return Times this listener has been called + */ + public int getCount() { + return count; + } + + /** + * Gets the total time calls to this listener have taken + * + * @return Total time for all calls of this listener + */ + public long getTotalTime() { + return totalTime; + } + + /** + * Gets the first event this listener handled + * + * @return An event handled by this RegisteredListener + */ + public Event getEvent() { + return event; + } + + /** + * Gets whether this listener has handled multiple events + * + * @return True if this listener has handled multiple events + */ + public boolean hasMultiple() { + return multiple; + } +} diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java index 5bc74be7..ba128fd9 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java @@ -45,7 +45,6 @@ public abstract class JavaPlugin implements Plugin { private EbeanServer ebean = null; private FileConfiguration newConfig = null; private File configFile = null; - private long[] timings = new long[Event.Type.values().length]; private PluginLogger logger = null; public JavaPlugin() {} @@ -374,18 +373,6 @@ public abstract class JavaPlugin implements Plugin { return logger; } - public long getTiming(Event.Type type) { - return timings[type.ordinal()]; - } - - public void incTiming(Event.Type type, long delta) { - timings[type.ordinal()] += delta; - } - - public void resetTimings() { - timings = new long[Event.Type.values().length]; - } - @Override public String toString() { return getDescription().getFullName(); diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java index 874397e3..2099fbda 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java @@ -992,6 +992,7 @@ public class JavaPluginLoader implements PluginLoader { } public Map, Set> createRegisteredListeners(Listener listener, final Plugin plugin) { + boolean useTimings = server.getPluginManager().useTimings(); Map, Set> ret = new HashMap, Set>(); Method[] methods; try { @@ -1016,7 +1017,7 @@ public class JavaPluginLoader implements PluginLoader { eventSet = new HashSet(); ret.put(eventClass, eventSet); } - eventSet.add(new RegisteredListener(listener, new EventExecutor() { + EventExecutor executor = new EventExecutor() { public void execute(Listener listener, Event event) throws EventException { try { if (!eventClass.isAssignableFrom(event.getClass())) { @@ -1027,7 +1028,12 @@ public class JavaPluginLoader implements PluginLoader { throw new EventException(t); } } - }, eh.priority(), plugin)); + }; + if (useTimings) { + eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin)); + } else { + eventSet.add(new RegisteredListener(listener, executor, eh.priority(), plugin)); + } } return ret; } -- cgit v1.2.3