From 36653a31875550e83940db62acd24034e53c2b93 Mon Sep 17 00:00:00 2001 From: Mike Primm Date: Wed, 23 Nov 2011 00:54:22 +0800 Subject: [PATCH] Add triggered render statistics, new /dynmap triggerstats command --- src/main/java/org/dynmap/DynmapPlugin.java | 39 +++++----- src/main/java/org/dynmap/MapManager.java | 72 ++++++++++++++++--- src/main/java/org/dynmap/MapTile.java | 8 +-- .../org/dynmap/kzedmap/KzedZoomedMapTile.java | 2 +- src/main/resources/plugin.yml | 3 +- 5 files changed, 87 insertions(+), 37 deletions(-) diff --git a/src/main/java/org/dynmap/DynmapPlugin.java b/src/main/java/org/dynmap/DynmapPlugin.java index 7d62ba77..52ffc5e5 100644 --- a/src/main/java/org/dynmap/DynmapPlugin.java +++ b/src/main/java/org/dynmap/DynmapPlugin.java @@ -222,6 +222,8 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { permissions = new OpPermissions(new String[] { "fullrender", "cancelrender", "radiusrender", "resetstats", "reload", "purgequeue" }); dataDirectory = this.getDataFolder(); + if(dataDirectory.exists() == false) + dataDirectory.mkdirs(); /* Initialize confguration.txt if needed */ File f = new File(this.getDataFolder(), "configuration.txt"); @@ -432,7 +434,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { Location loc = event.getBlock().getLocation(); mapManager.sscache.invalidateSnapshot(loc); if(onplace) { - mapManager.touch(loc); + mapManager.touch(loc, "blockplace"); } } @@ -443,7 +445,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { Location loc = event.getBlock().getLocation(); mapManager.sscache.invalidateSnapshot(loc); if(onbreak) { - mapManager.touch(loc); + mapManager.touch(loc, "blockbreak"); } } @@ -454,7 +456,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { Location loc = event.getBlock().getLocation(); mapManager.sscache.invalidateSnapshot(loc); if(onleaves) { - mapManager.touch(loc); + mapManager.touch(loc, "leavesdecay"); } } @@ -465,7 +467,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { Location loc = event.getBlock().getLocation(); mapManager.sscache.invalidateSnapshot(loc); if(onburn) { - mapManager.touch(loc); + mapManager.touch(loc, "blockburn"); } } @@ -476,7 +478,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { Location loc = event.getBlock().getLocation(); mapManager.sscache.invalidateSnapshot(loc); if(onblockform) { - mapManager.touch(loc); + mapManager.touch(loc, "blockform"); } } @@ -487,7 +489,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { Location loc = event.getBlock().getLocation(); mapManager.sscache.invalidateSnapshot(loc); if(onblockfade) { - mapManager.touch(loc); + mapManager.touch(loc, "blockfade"); } } @@ -498,7 +500,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { Location loc = event.getBlock().getLocation(); mapManager.sscache.invalidateSnapshot(loc); if(onblockspread) { - mapManager.touch(loc); + mapManager.touch(loc, "blockspread"); } } @@ -516,7 +518,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { dir = BlockFace.NORTH; } if(onpiston) { - mapManager.touchVolume(loc, b.getRelative(dir, 2).getLocation()); + mapManager.touchVolume(loc, b.getRelative(dir, 2).getLocation(), "pistonretract"); } for(int i = 0; i < 2; i++) { b = b.getRelative(dir, 1); @@ -537,7 +539,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { dir = BlockFace.NORTH; } if(onpiston) { - mapManager.touchVolume(loc, b.getRelative(dir, 1+event.getLength()).getLocation()); + mapManager.touchVolume(loc, b.getRelative(dir, 1+event.getLength()).getLocation(), "pistonextend"); } for(int i = 0; i < 1+event.getLength(); i++) { b = b.getRelative(dir, 1); @@ -577,12 +579,12 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { PlayerListener playerTrigger = new PlayerListener() { @Override public void onPlayerJoin(PlayerJoinEvent event) { - mapManager.touch(event.getPlayer().getLocation()); + mapManager.touch(event.getPlayer().getLocation(), "playerjoin"); } @Override public void onPlayerMove(PlayerMoveEvent event) { - mapManager.touch(event.getPlayer().getLocation()); + mapManager.touch(event.getPlayer().getLocation(), "playermove"); } }; @@ -602,7 +604,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { Location loc = b.getLocation(); mapManager.sscache.invalidateSnapshot(loc); if(onexplosion) { - mapManager.touch(loc); + mapManager.touch(loc, "entityexplode"); } } } @@ -620,13 +622,13 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { /* Touch extreme corners */ int x = event.getChunk().getX() << 4; int z = event.getChunk().getZ() << 4; - mapManager.touchVolume(new Location(event.getWorld(), x, 0, z), new Location(event.getWorld(), x+16, 128, z+16)); + mapManager.touchVolume(new Location(event.getWorld(), x, 0, z), new Location(event.getWorld(), x+16, 128, z+16), "chunkload"); } @Override public void onChunkPopulate(ChunkPopulateEvent event) { int x = event.getChunk().getX() << 4; int z = event.getChunk().getZ() << 4; - mapManager.touchVolume(new Location(event.getWorld(), x, 0, z), new Location(event.getWorld(), x+16, 128, z+16)); + mapManager.touchVolume(new Location(event.getWorld(), x, 0, z), new Location(event.getWorld(), x+16, 128, z+16), "chunkgenerate"); } @Override public void onWorldLoad(WorldLoadEvent event) { @@ -725,6 +727,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { "radiusrender", "reload", "stats", + "triggerstats", "resetstats", "sendtoweb", "purgequeue" })); @@ -753,7 +756,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { if (c.equals("render") && checkPlayerPermission(sender,"render")) { if (player != null) { - int invalidates = mapManager.touch(player.getLocation()); + int invalidates = mapManager.touch(player.getLocation(), "render"); sender.sendMessage("Queued " + invalidates + " tiles" + (invalidates == 0 ? " (world is not loaded?)" : "...")); @@ -860,6 +863,8 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { mapManager.printStats(sender, null); else mapManager.printStats(sender, args[1]); + } else if (c.equals("triggerstats") && checkPlayerPermission(sender, "stats")) { + mapManager.printTriggerStats(sender); } else if (c.equals("resetstats") && checkPlayerPermission(sender, "resetstats")) { if(args.length == 1) mapManager.resetStats(sender, null); @@ -1322,9 +1327,9 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI { public int triggerRenderOfVolume(Location l0, Location l1) { if(mapManager != null) { if(l1 == null) - return mapManager.touch(l0); + return mapManager.touch(l0, "api"); else - return mapManager.touchVolume(l0, l1); + return mapManager.touchVolume(l0, l1, "api"); } return 0; } diff --git a/src/main/java/org/dynmap/MapManager.java b/src/main/java/org/dynmap/MapManager.java index 6ece378f..754ab86b 100644 --- a/src/main/java/org/dynmap/MapManager.java +++ b/src/main/java/org/dynmap/MapManager.java @@ -80,6 +80,14 @@ public class MapManager { int updatedcnt; int transparentcnt; } + + private HashMap trigstats = new HashMap(); + + private static class TriggerStats { + long callsmade; + long callswithtiles; + long tilesqueued; + } public DynmapWorld getWorld(String name) { DynmapWorld world = worldsLookup.get(name); @@ -862,8 +870,8 @@ public class MapManager { for(ConfigurationNode tile : tiles) { MapTile mt = MapTile.restoreTile(w, tile); /* Restore tile, if possible */ if(mt != null) { - invalidateTile(mt); - cnt++; + if(invalidateTile(mt)) + cnt++; } } if(cnt > 0) @@ -916,7 +924,7 @@ public class MapManager { } } - public int touch(Location l) { + public int touch(Location l, String reason) { DynmapWorld world = getWorld(l.getWorld().getName()); if (world == null) return 0; @@ -924,14 +932,26 @@ public class MapManager { for (int i = 0; i < world.maps.size(); i++) { MapTile[] tiles = world.maps.get(i).getTiles(l); for (int j = 0; j < tiles.length; j++) { - invalidateTile(tiles[j]); - invalidates++; + if(invalidateTile(tiles[j])) + invalidates++; + } + } + if(reason != null) { + TriggerStats ts = trigstats.get(reason); + if(ts == null) { + ts = new TriggerStats(); + trigstats.put(reason, ts); + } + ts.callsmade++; + if(invalidates > 0) { + ts.callswithtiles++; + ts.tilesqueued += invalidates; } } return invalidates; } - public int touchVolume(Location l0, Location l1) { + public int touchVolume(Location l0, Location l1, String reason) { DynmapWorld world = getWorld(l0.getWorld().getName()); if (world == null) return 0; @@ -939,16 +959,27 @@ public class MapManager { for (int i = 0; i < world.maps.size(); i++) { MapTile[] tiles = world.maps.get(i).getTiles(l0, l1); for (int j = 0; j < tiles.length; j++) { - invalidateTile(tiles[j]); - invalidates++; + if(invalidateTile(tiles[j])) + invalidates++; + } + } + if(reason != null) { + TriggerStats ts = trigstats.get(reason); + if(ts == null) { + ts = new TriggerStats(); + trigstats.put(reason, ts); + } + ts.callsmade++; + if(invalidates > 0) { + ts.callswithtiles++; + ts.tilesqueued += invalidates; } } return invalidates; } - public void invalidateTile(MapTile tile) { - if(tileQueue.push(tile)) - Debug.debug("Invalidating tile " + tile.getFilename()); + public boolean invalidateTile(MapTile tile) { + return tileQueue.push(tile); } public static boolean scheduleDelayedJob(Runnable job, long delay_in_msec) { @@ -1149,6 +1180,19 @@ public class MapManager { act += wn + " "; sender.sendMessage(" Active render jobs: " + act); } + /** + * Print trigger statistics command + */ + public void printTriggerStats(CommandSender sender) { + sender.sendMessage("Render Trigger Statistics:"); + synchronized(lock) { + for(String k: new TreeSet(trigstats.keySet())) { + TriggerStats ts = trigstats.get(k); + sender.sendMessage(" " + k + ": calls=" + ts.callsmade + ", calls-adding-tiles=" + ts.callswithtiles + ", tiles-added=" + ts.tilesqueued); + } + } + } + /** * Reset statistics */ @@ -1163,6 +1207,12 @@ public class MapManager { ms.updatedcnt = 0; ms.transparentcnt = 0; } + for(String k : trigstats.keySet()) { + TriggerStats ts = trigstats.get(k); + ts.callsmade = 0; + ts.callswithtiles = 0; + ts.tilesqueued = 0; + } } sscache.resetStats(); sender.sendMessage("Tile Render Statistics reset"); diff --git a/src/main/java/org/dynmap/MapTile.java b/src/main/java/org/dynmap/MapTile.java index 30f9df25..1d67ae40 100644 --- a/src/main/java/org/dynmap/MapTile.java +++ b/src/main/java/org/dynmap/MapTile.java @@ -38,13 +38,7 @@ public abstract class MapTile { } @Override - public boolean equals(Object obj) { - if (obj instanceof MapTile) { - MapTile t = (MapTile)obj; - return getFilename().equals(t.getFilename()) && getWorld().equals(t.getWorld()); - } - return super.equals(obj); - } + public abstract boolean equals(Object obj); public abstract String getKey(); diff --git a/src/main/java/org/dynmap/kzedmap/KzedZoomedMapTile.java b/src/main/java/org/dynmap/kzedmap/KzedZoomedMapTile.java index 9e92f663..63b401a0 100644 --- a/src/main/java/org/dynmap/kzedmap/KzedZoomedMapTile.java +++ b/src/main/java/org/dynmap/kzedmap/KzedZoomedMapTile.java @@ -81,7 +81,7 @@ public class KzedZoomedMapTile extends MapTile { if (obj instanceof KzedZoomedMapTile) { return ((KzedZoomedMapTile) obj).originalTile.equals(originalTile); } - return super.equals(obj); + return false; } diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index d87ada6c..4737871a 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -21,6 +21,7 @@ commands: / cancelrender world - Cancels any active renders of world 'world' / stats - Show render statistics. / stats world - Show render statistics for maps on world 'world'. + / triggerstats - Show render trigger statistics / resetstats - Reset render statistics. / resetstats world - Reset render statistics for maps on world 'world'. / sendtoweb msg - Send message to web users @@ -125,7 +126,7 @@ permissions: description: Allows /dynmap reload default: op dynmap.stats: - description: Allows /dynmap stats or /dynmap stats + description: Allows /dynmap stats, /dynmap stats , or /dynmap triggerstats default: true dynmap.resetstats: description: Allows /dynmap resetstats or /dynmap resetstats