Add more metrics to chunk loading (for testing)

This commit is contained in:
Mike Primm 2014-02-03 21:36:43 -06:00
parent eeffa4f98d
commit 926d2a3dbc
2 changed files with 79 additions and 4 deletions

View File

@ -955,7 +955,11 @@ public class DynmapPlugin extends JavaPlugin implements DynmapAPI {
else { else {
dsender = new BukkitCommandSender(sender); dsender = new BukkitCommandSender(sender);
} }
return core.processCommand(dsender, cmd.getName(), commandLabel, args); boolean rslt = core.processCommand(dsender, cmd.getName(), commandLabel, args);
if (commandLabel.equals("dynmap") && (args.length > 0) && (args[0].equals("stats"))) {
NewMapChunkCache.dumpStats(sender);
}
return rslt;
} }

View File

@ -8,6 +8,7 @@ import java.util.Map;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.command.CommandSender;
import org.bukkit.ChunkSnapshot; import org.bukkit.ChunkSnapshot;
import org.dynmap.DynmapChunk; import org.dynmap.DynmapChunk;
import org.dynmap.DynmapCore; import org.dynmap.DynmapCore;
@ -804,9 +805,44 @@ public class NewMapChunkCache implements MapChunkCache {
return ss; return ss;
} }
public enum TimeStep {
loadChunk,
getChunkAt,
getChunkSnapshot,
getTileEntityData,
unloadChunkNoSave,
unloadChunkRequest,
isChunkLoaded,
isInUnloadQueue,
getEmptyChunkSnapshot,
getSnapshotCache,
putSnapshotCache,
loadLoop,
loadCalls
}
public static long[] timetot = new long[16];
public static long[] cnttot = new long[16];
public static long[] timestart = new long[16];
private static final void startTime(TimeStep idx) {
timestart[idx.ordinal()] = System.nanoTime();
}
private static final void stopTime(TimeStep idx) {
int ord = idx.ordinal();
timetot[ord] += System.nanoTime() - timestart[ord];
cnttot[ord]++;
}
public static void dumpStats(CommandSender sender) {
for (TimeStep ts : TimeStep.values()) {
sender.sendMessage(" " + ts + ": " + timetot[ts.ordinal()] + "ns, " + cnttot[ts.ordinal()] + " calls, " + (0.001 * timetot[ts.ordinal()] / cnttot[ts.ordinal()]) + "us/call" );
}
}
public int loadChunks(int max_to_load) { public int loadChunks(int max_to_load) {
if(dw.isLoaded() == false) if(dw.isLoaded() == false)
return 0; return 0;
startTime(TimeStep.loadCalls);
long t0 = System.nanoTime(); long t0 = System.nanoTime();
Object queue = helper.getUnloadQueue(helper.getNMSWorld(w)); Object queue = helper.getUnloadQueue(helper.getNMSWorld(w));
@ -818,6 +854,8 @@ public class NewMapChunkCache implements MapChunkCache {
//boolean isnormral = w.getEnvironment() == Environment.NORMAL; //boolean isnormral = w.getEnvironment() == Environment.NORMAL;
// Load the required chunks. // Load the required chunks.
while((cnt < max_to_load) && iterator.hasNext()) { while((cnt < max_to_load) && iterator.hasNext()) {
startTime(TimeStep.loadLoop);
DynmapChunk chunk = iterator.next(); DynmapChunk chunk = iterator.next();
boolean vis = true; boolean vis = true;
if(visible_limits != null) { if(visible_limits != null) {
@ -841,7 +879,10 @@ public class NewMapChunkCache implements MapChunkCache {
ChunkSnapshot ss = null; ChunkSnapshot ss = null;
long inhabited_ticks = 0; long inhabited_ticks = 0;
DynIntHashMap tileData = null; DynIntHashMap tileData = null;
startTime(TimeStep.getSnapshotCache);
SnapshotRec ssr = DynmapPlugin.plugin.sscache.getSnapshot(dw.getName(), chunk.x, chunk.z, blockdata, biome, biomeraw, highesty); SnapshotRec ssr = DynmapPlugin.plugin.sscache.getSnapshot(dw.getName(), chunk.x, chunk.z, blockdata, biome, biomeraw, highesty);
stopTime(TimeStep.getSnapshotCache);
if(ssr != null) { if(ssr != null) {
ss = ssr.ss; ss = ssr.ss;
inhabited_ticks = ssr.inhabitedTicks; inhabited_ticks = ssr.inhabitedTicks;
@ -857,32 +898,47 @@ public class NewMapChunkCache implements MapChunkCache {
snaparray[idx] = ss; snaparray[idx] = ss;
snaptile[idx] = ssr.tileData; snaptile[idx] = ssr.tileData;
inhabitedTicks[idx] = inhabited_ticks; inhabitedTicks[idx] = inhabited_ticks;
stopTime(TimeStep.loadLoop);
continue; continue;
} }
chunks_attempted++; chunks_attempted++;
startTime(TimeStep.isChunkLoaded);
boolean wasLoaded = w.isChunkLoaded(chunk.x, chunk.z); boolean wasLoaded = w.isChunkLoaded(chunk.x, chunk.z);
stopTime(TimeStep.isChunkLoaded);
boolean didload = false; boolean didload = false;
boolean isunloadpending = false; boolean isunloadpending = false;
if (queue != null) { if (queue != null) {
startTime(TimeStep.isInUnloadQueue);
isunloadpending = helper.isInUnloadQueue(queue, chunk.x, chunk.z); isunloadpending = helper.isInUnloadQueue(queue, chunk.x, chunk.z);
stopTime(TimeStep.isInUnloadQueue);
} }
if (isunloadpending) { /* Workaround: can't be pending if not loaded */ if (isunloadpending) { /* Workaround: can't be pending if not loaded */
wasLoaded = true; wasLoaded = true;
} }
try { try {
didload = w.loadChunk(chunk.x, chunk.z, false); startTime(TimeStep.loadChunk);
try {
didload = w.loadChunk(chunk.x, chunk.z, false);
} finally {
stopTime(TimeStep.loadChunk);
}
} catch (Throwable t) { /* Catch chunk error from Bukkit */ } catch (Throwable t) { /* Catch chunk error from Bukkit */
Log.warning("Bukkit error loading chunk " + chunk.x + "," + chunk.z + " on " + w.getName()); Log.warning("Bukkit error loading chunk " + chunk.x + "," + chunk.z + " on " + w.getName());
if(!wasLoaded) { /* If wasn't loaded, we loaded it if it now is */ if(!wasLoaded) { /* If wasn't loaded, we loaded it if it now is */
startTime(TimeStep.isChunkLoaded);
didload = w.isChunkLoaded(chunk.x, chunk.z); didload = w.isChunkLoaded(chunk.x, chunk.z);
stopTime(TimeStep.isChunkLoaded);
} }
} }
/* If it did load, make cache of it */ /* If it did load, make cache of it */
if(didload) { if(didload) {
tileData = new DynIntHashMap(); tileData = new DynIntHashMap();
startTime(TimeStep.getChunkAt);
Chunk c = w.getChunkAt(chunk.x, chunk.z); /* Get the chunk */ Chunk c = w.getChunkAt(chunk.x, chunk.z); /* Get the chunk */
stopTime(TimeStep.getChunkAt);
/* Get inhabited ticks count */ /* Get inhabited ticks count */
inhabited_ticks = helper.getInhabitedTicks(c); inhabited_ticks = helper.getInhabitedTicks(c);
if(!vis) { if(!vis) {
@ -895,11 +951,14 @@ public class NewMapChunkCache implements MapChunkCache {
} }
else { else {
if(blockdata || highesty) { if(blockdata || highesty) {
startTime(TimeStep.getChunkSnapshot);
ss = c.getChunkSnapshot(highesty, biome, biomeraw); ss = c.getChunkSnapshot(highesty, biome, biomeraw);
stopTime(TimeStep.getChunkSnapshot);
if(use_spout) { if(use_spout) {
ss = checkSpoutData(c, ss); ss = checkSpoutData(c, ss);
} }
/* Get tile entity data */ /* Get tile entity data */
startTime(TimeStep.getTileEntityData);
List<Object> vals = new ArrayList<Object>(); List<Object> vals = new ArrayList<Object>();
Map<?,?> tileents = helper.getTileEntitiesForChunk(c); Map<?,?> tileents = helper.getTileEntitiesForChunk(c);
for(Object t : tileents.values()) { for(Object t : tileents.values()) {
@ -928,15 +987,21 @@ public class NewMapChunkCache implements MapChunkCache {
} }
} }
} }
stopTime(TimeStep.getTileEntityData);
} }
else else {
startTime(TimeStep.getEmptyChunkSnapshot);
ss = w.getEmptyChunkSnapshot(chunk.x, chunk.z, biome, biomeraw); ss = w.getEmptyChunkSnapshot(chunk.x, chunk.z, biome, biomeraw);
stopTime(TimeStep.getEmptyChunkSnapshot);
}
if(ss != null) { if(ss != null) {
ssr = new SnapshotRec(); ssr = new SnapshotRec();
ssr.ss = ss; ssr.ss = ss;
ssr.inhabitedTicks = inhabited_ticks; ssr.inhabitedTicks = inhabited_ticks;
ssr.tileData = tileData; ssr.tileData = tileData;
startTime(TimeStep.putSnapshotCache);
DynmapPlugin.plugin.sscache.putSnapshot(dw.getName(), chunk.x, chunk.z, ssr, blockdata, biome, biomeraw, highesty); DynmapPlugin.plugin.sscache.putSnapshot(dw.getName(), chunk.x, chunk.z, ssr, blockdata, biome, biomeraw, highesty);
stopTime(TimeStep.putSnapshotCache);
} }
} }
int chunkIndex = (chunk.x-x_min) + (chunk.z - z_min)*x_dim; int chunkIndex = (chunk.x-x_min) + (chunk.z - z_min)*x_dim;
@ -953,13 +1018,18 @@ public class NewMapChunkCache implements MapChunkCache {
* while the actual in-use chunk area for a player where the chunks are managed * while the actual in-use chunk area for a player where the chunks are managed
* by the MC base server is 21x21 (or about a 160 block radius). * by the MC base server is 21x21 (or about a 160 block radius).
* Also, if we did generate it, need to save it */ * Also, if we did generate it, need to save it */
startTime(TimeStep.unloadChunkNoSave);
helper.unloadChunkNoSave(w, c, chunk.x, chunk.z); helper.unloadChunkNoSave(w, c, chunk.x, chunk.z);
stopTime(TimeStep.unloadChunkNoSave);
} }
else if (isunloadpending) { /* Else, if loaded and unload is pending */ else if (isunloadpending) { /* Else, if loaded and unload is pending */
startTime(TimeStep.unloadChunkRequest);
w.unloadChunkRequest(chunk.x, chunk.z); /* Request new unload */ w.unloadChunkRequest(chunk.x, chunk.z); /* Request new unload */
stopTime(TimeStep.unloadChunkRequest);
} }
} }
cnt++; cnt++;
stopTime(TimeStep.loadLoop);
} }
DynmapCore.setIgnoreChunkLoads(false); DynmapCore.setIgnoreChunkLoads(false);
@ -974,6 +1044,7 @@ public class NewMapChunkCache implements MapChunkCache {
} }
} }
total_loadtime += System.nanoTime() - t0; total_loadtime += System.nanoTime() - t0;
stopTime(TimeStep.loadCalls);
return cnt; return cnt;
} }