Add triggered render statistics, new /dynmap triggerstats command

This commit is contained in:
Mike Primm 2011-11-23 00:54:22 +08:00 committed by mikeprimm
parent f886fbc614
commit 36653a3187
5 changed files with 87 additions and 37 deletions

View File

@ -222,6 +222,8 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
permissions = new OpPermissions(new String[] { "fullrender", "cancelrender", "radiusrender", "resetstats", "reload", "purgequeue" }); permissions = new OpPermissions(new String[] { "fullrender", "cancelrender", "radiusrender", "resetstats", "reload", "purgequeue" });
dataDirectory = this.getDataFolder(); dataDirectory = this.getDataFolder();
if(dataDirectory.exists() == false)
dataDirectory.mkdirs();
/* Initialize confguration.txt if needed */ /* Initialize confguration.txt if needed */
File f = new File(this.getDataFolder(), "configuration.txt"); File f = new File(this.getDataFolder(), "configuration.txt");
@ -432,7 +434,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
Location loc = event.getBlock().getLocation(); Location loc = event.getBlock().getLocation();
mapManager.sscache.invalidateSnapshot(loc); mapManager.sscache.invalidateSnapshot(loc);
if(onplace) { 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(); Location loc = event.getBlock().getLocation();
mapManager.sscache.invalidateSnapshot(loc); mapManager.sscache.invalidateSnapshot(loc);
if(onbreak) { 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(); Location loc = event.getBlock().getLocation();
mapManager.sscache.invalidateSnapshot(loc); mapManager.sscache.invalidateSnapshot(loc);
if(onleaves) { 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(); Location loc = event.getBlock().getLocation();
mapManager.sscache.invalidateSnapshot(loc); mapManager.sscache.invalidateSnapshot(loc);
if(onburn) { 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(); Location loc = event.getBlock().getLocation();
mapManager.sscache.invalidateSnapshot(loc); mapManager.sscache.invalidateSnapshot(loc);
if(onblockform) { 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(); Location loc = event.getBlock().getLocation();
mapManager.sscache.invalidateSnapshot(loc); mapManager.sscache.invalidateSnapshot(loc);
if(onblockfade) { 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(); Location loc = event.getBlock().getLocation();
mapManager.sscache.invalidateSnapshot(loc); mapManager.sscache.invalidateSnapshot(loc);
if(onblockspread) { if(onblockspread) {
mapManager.touch(loc); mapManager.touch(loc, "blockspread");
} }
} }
@ -516,7 +518,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
dir = BlockFace.NORTH; dir = BlockFace.NORTH;
} }
if(onpiston) { 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++) { for(int i = 0; i < 2; i++) {
b = b.getRelative(dir, 1); b = b.getRelative(dir, 1);
@ -537,7 +539,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
dir = BlockFace.NORTH; dir = BlockFace.NORTH;
} }
if(onpiston) { 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++) { for(int i = 0; i < 1+event.getLength(); i++) {
b = b.getRelative(dir, 1); b = b.getRelative(dir, 1);
@ -577,12 +579,12 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
PlayerListener playerTrigger = new PlayerListener() { PlayerListener playerTrigger = new PlayerListener() {
@Override @Override
public void onPlayerJoin(PlayerJoinEvent event) { public void onPlayerJoin(PlayerJoinEvent event) {
mapManager.touch(event.getPlayer().getLocation()); mapManager.touch(event.getPlayer().getLocation(), "playerjoin");
} }
@Override @Override
public void onPlayerMove(PlayerMoveEvent event) { 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(); Location loc = b.getLocation();
mapManager.sscache.invalidateSnapshot(loc); mapManager.sscache.invalidateSnapshot(loc);
if(onexplosion) { if(onexplosion) {
mapManager.touch(loc); mapManager.touch(loc, "entityexplode");
} }
} }
} }
@ -620,13 +622,13 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
/* Touch extreme corners */ /* Touch extreme corners */
int x = event.getChunk().getX() << 4; int x = event.getChunk().getX() << 4;
int z = event.getChunk().getZ() << 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 @Override
public void onChunkPopulate(ChunkPopulateEvent event) { public void onChunkPopulate(ChunkPopulateEvent event) {
int x = event.getChunk().getX() << 4; int x = event.getChunk().getX() << 4;
int z = event.getChunk().getZ() << 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 @Override
public void onWorldLoad(WorldLoadEvent event) { public void onWorldLoad(WorldLoadEvent event) {
@ -725,6 +727,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
"radiusrender", "radiusrender",
"reload", "reload",
"stats", "stats",
"triggerstats",
"resetstats", "resetstats",
"sendtoweb", "sendtoweb",
"purgequeue" })); "purgequeue" }));
@ -753,7 +756,7 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
if (c.equals("render") && checkPlayerPermission(sender,"render")) { if (c.equals("render") && checkPlayerPermission(sender,"render")) {
if (player != null) { if (player != null) {
int invalidates = mapManager.touch(player.getLocation()); int invalidates = mapManager.touch(player.getLocation(), "render");
sender.sendMessage("Queued " + invalidates + " tiles" + (invalidates == 0 sender.sendMessage("Queued " + invalidates + " tiles" + (invalidates == 0
? " (world is not loaded?)" ? " (world is not loaded?)"
: "...")); : "..."));
@ -860,6 +863,8 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
mapManager.printStats(sender, null); mapManager.printStats(sender, null);
else else
mapManager.printStats(sender, args[1]); mapManager.printStats(sender, args[1]);
} else if (c.equals("triggerstats") && checkPlayerPermission(sender, "stats")) {
mapManager.printTriggerStats(sender);
} else if (c.equals("resetstats") && checkPlayerPermission(sender, "resetstats")) { } else if (c.equals("resetstats") && checkPlayerPermission(sender, "resetstats")) {
if(args.length == 1) if(args.length == 1)
mapManager.resetStats(sender, null); mapManager.resetStats(sender, null);
@ -1322,9 +1327,9 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
public int triggerRenderOfVolume(Location l0, Location l1) { public int triggerRenderOfVolume(Location l0, Location l1) {
if(mapManager != null) { if(mapManager != null) {
if(l1 == null) if(l1 == null)
return mapManager.touch(l0); return mapManager.touch(l0, "api");
else else
return mapManager.touchVolume(l0, l1); return mapManager.touchVolume(l0, l1, "api");
} }
return 0; return 0;
} }

View File

@ -80,6 +80,14 @@ public class MapManager {
int updatedcnt; int updatedcnt;
int transparentcnt; int transparentcnt;
} }
private HashMap<String, TriggerStats> trigstats = new HashMap<String, TriggerStats>();
private static class TriggerStats {
long callsmade;
long callswithtiles;
long tilesqueued;
}
public DynmapWorld getWorld(String name) { public DynmapWorld getWorld(String name) {
DynmapWorld world = worldsLookup.get(name); DynmapWorld world = worldsLookup.get(name);
@ -862,8 +870,8 @@ public class MapManager {
for(ConfigurationNode tile : tiles) { for(ConfigurationNode tile : tiles) {
MapTile mt = MapTile.restoreTile(w, tile); /* Restore tile, if possible */ MapTile mt = MapTile.restoreTile(w, tile); /* Restore tile, if possible */
if(mt != null) { if(mt != null) {
invalidateTile(mt); if(invalidateTile(mt))
cnt++; cnt++;
} }
} }
if(cnt > 0) 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()); DynmapWorld world = getWorld(l.getWorld().getName());
if (world == null) if (world == null)
return 0; return 0;
@ -924,14 +932,26 @@ public class MapManager {
for (int i = 0; i < world.maps.size(); i++) { for (int i = 0; i < world.maps.size(); i++) {
MapTile[] tiles = world.maps.get(i).getTiles(l); MapTile[] tiles = world.maps.get(i).getTiles(l);
for (int j = 0; j < tiles.length; j++) { for (int j = 0; j < tiles.length; j++) {
invalidateTile(tiles[j]); if(invalidateTile(tiles[j]))
invalidates++; 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; return invalidates;
} }
public int touchVolume(Location l0, Location l1) { public int touchVolume(Location l0, Location l1, String reason) {
DynmapWorld world = getWorld(l0.getWorld().getName()); DynmapWorld world = getWorld(l0.getWorld().getName());
if (world == null) if (world == null)
return 0; return 0;
@ -939,16 +959,27 @@ public class MapManager {
for (int i = 0; i < world.maps.size(); i++) { for (int i = 0; i < world.maps.size(); i++) {
MapTile[] tiles = world.maps.get(i).getTiles(l0, l1); MapTile[] tiles = world.maps.get(i).getTiles(l0, l1);
for (int j = 0; j < tiles.length; j++) { for (int j = 0; j < tiles.length; j++) {
invalidateTile(tiles[j]); if(invalidateTile(tiles[j]))
invalidates++; 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; return invalidates;
} }
public void invalidateTile(MapTile tile) { public boolean invalidateTile(MapTile tile) {
if(tileQueue.push(tile)) return tileQueue.push(tile);
Debug.debug("Invalidating tile " + tile.getFilename());
} }
public static boolean scheduleDelayedJob(Runnable job, long delay_in_msec) { public static boolean scheduleDelayedJob(Runnable job, long delay_in_msec) {
@ -1149,6 +1180,19 @@ public class MapManager {
act += wn + " "; act += wn + " ";
sender.sendMessage(" Active render jobs: " + act); 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<String>(trigstats.keySet())) {
TriggerStats ts = trigstats.get(k);
sender.sendMessage(" " + k + ": calls=" + ts.callsmade + ", calls-adding-tiles=" + ts.callswithtiles + ", tiles-added=" + ts.tilesqueued);
}
}
}
/** /**
* Reset statistics * Reset statistics
*/ */
@ -1163,6 +1207,12 @@ public class MapManager {
ms.updatedcnt = 0; ms.updatedcnt = 0;
ms.transparentcnt = 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(); sscache.resetStats();
sender.sendMessage("Tile Render Statistics reset"); sender.sendMessage("Tile Render Statistics reset");

View File

@ -38,13 +38,7 @@ public abstract class MapTile {
} }
@Override @Override
public boolean equals(Object obj) { public abstract 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 String getKey(); public abstract String getKey();

View File

@ -81,7 +81,7 @@ public class KzedZoomedMapTile extends MapTile {
if (obj instanceof KzedZoomedMapTile) { if (obj instanceof KzedZoomedMapTile) {
return ((KzedZoomedMapTile) obj).originalTile.equals(originalTile); return ((KzedZoomedMapTile) obj).originalTile.equals(originalTile);
} }
return super.equals(obj); return false;
} }

View File

@ -21,6 +21,7 @@ commands:
/<command> cancelrender world - Cancels any active renders of world 'world' /<command> cancelrender world - Cancels any active renders of world 'world'
/<command> stats - Show render statistics. /<command> stats - Show render statistics.
/<command> stats world - Show render statistics for maps on world 'world'. /<command> stats world - Show render statistics for maps on world 'world'.
/<command> triggerstats - Show render trigger statistics
/<command> resetstats - Reset render statistics. /<command> resetstats - Reset render statistics.
/<command> resetstats world - Reset render statistics for maps on world 'world'. /<command> resetstats world - Reset render statistics for maps on world 'world'.
/<command> sendtoweb msg - Send message to web users /<command> sendtoweb msg - Send message to web users
@ -125,7 +126,7 @@ permissions:
description: Allows /dynmap reload description: Allows /dynmap reload
default: op default: op
dynmap.stats: dynmap.stats:
description: Allows /dynmap stats or /dynmap stats <world> description: Allows /dynmap stats, /dynmap stats <world>, or /dynmap triggerstats
default: true default: true
dynmap.resetstats: dynmap.resetstats:
description: Allows /dynmap resetstats or /dynmap resetstats <world> description: Allows /dynmap resetstats or /dynmap resetstats <world>