PaperMC/CraftBukkit-Patches/0012-Spigot-Timings.patch
Thinkofdeath 461353e2cb SPIGOT-522: Remove the global api cache option
This was useful when plugins first started upgrading to uuid because each
plugin would implement their own way for grabbing uuid's from mojang. Because
none of them shared the result they would quickly hit the limits on the api
causing the conversion to either fail or pause for long periods of time. The
global api cache was a (very hacky) way to force all plugins to share a cache
but caused a few issues with plugins that expected a full implementation of
the HTTPURLConnection. Due to the fact that most servers/plugins have updated
now it seems to be a good time to remove this as its usefulness mostly has
expired.
2015-02-06 09:03:19 -06:00

893 lines
41 KiB
Diff

From 29c05c2c47f5a655cf0e5aa4131ca33c891ec256 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Thu, 10 Jan 2013 00:18:11 -0500
Subject: [PATCH] Spigot Timings
Overhauls the Timings System adding performance tracking all around the Minecraft Server
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index bf48742..867caca 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -864,6 +864,7 @@ public class Chunk {
}
public void loadNearby(IChunkProvider ichunkprovider, IChunkProvider ichunkprovider1, int i, int j) {
+ world.timings.syncChunkLoadPostTimer.startTiming(); // Spigot
boolean flag = ichunkprovider.isChunkLoaded(i, j - 1);
boolean flag1 = ichunkprovider.isChunkLoaded(i + 1, j);
boolean flag2 = ichunkprovider.isChunkLoaded(i, j + 1);
@@ -910,6 +911,7 @@ public class Chunk {
}
}
+ world.timings.syncChunkLoadPostTimer.stopTiming(); // Spigot
}
public BlockPosition h(BlockPosition blockposition) {
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index a363af7..9ee7e75 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -130,6 +130,7 @@ public class ChunkProviderServer implements IChunkProvider {
// CraftBukkit end
if (chunk == null) {
+ world.timings.syncChunkLoadTimer.startTiming(); // Spigot
chunk = this.loadChunk(i, j);
if (chunk == null) {
if (this.chunkProvider == null) {
@@ -181,6 +182,7 @@ public class ChunkProviderServer implements IChunkProvider {
// CraftBukkit end
chunk.loadNearby(this, this, i, j);
+ world.timings.syncChunkLoadTimer.stopTiming(); // Spigot
}
return chunk;
@@ -215,7 +217,9 @@ public class ChunkProviderServer implements IChunkProvider {
if (chunk != null) {
chunk.setLastSaved(this.world.getTime());
if (this.chunkProvider != null) {
+ world.timings.syncChunkLoadStructuresTimer.startTiming(); // Spigot
this.chunkProvider.recreateStructures(chunk, i, j);
+ world.timings.syncChunkLoadStructuresTimer.stopTiming(); // Spigot
}
}
diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
index 33bb889..7caddb5 100644
--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java
+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
@@ -45,7 +45,9 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
// CraftBukkit start - Add async variant, provide compatibility
public Chunk a(World world, int i, int j) {
+ world.timings.syncChunkLoadDataTimer.startTiming(); // Spigot
Object[] data = loadChunk(world, i, j);
+ world.timings.syncChunkLoadDataTimer.stopTiming(); // Spigot
if (data != null) {
Chunk chunk = (Chunk) data[0];
NBTTagCompound nbttagcompound = (NBTTagCompound) data[1];
@@ -400,6 +402,7 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
public void loadEntities(Chunk chunk, NBTTagCompound nbttagcompound, World world) {
// CraftBukkit end
+ world.timings.syncChunkLoadEntitiesTimer.startTiming(); // Spigot
NBTTagList nbttaglist1 = nbttagcompound.getList("Entities", 10);
if (nbttaglist1 != null) {
@@ -425,7 +428,8 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
}
}
}
-
+ world.timings.syncChunkLoadEntitiesTimer.stopTiming(); // Spigot
+ world.timings.syncChunkLoadTileEntitiesTimer.startTiming(); // Spigot
NBTTagList nbttaglist2 = nbttagcompound.getList("TileEntities", 10);
if (nbttaglist2 != null) {
@@ -438,6 +442,8 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
}
}
}
+ world.timings.syncChunkLoadTileEntitiesTimer.stopTiming(); // Spigot
+ world.timings.syncChunkLoadTileTicksTimer.startTiming(); // Spigot
if (nbttagcompound.hasKeyOfType("TileTicks", 9)) {
NBTTagList nbttaglist3 = nbttagcompound.getList("TileTicks", 10);
@@ -457,6 +463,7 @@ public class ChunkRegionLoader implements IChunkLoader, IAsyncChunkSaver {
}
}
}
+ world.timings.syncChunkLoadTileTicksTimer.stopTiming(); // Spigot
// return chunk; // CraftBukkit
}
diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java
index 424b71d..390c6eb 100644
--- a/src/main/java/net/minecraft/server/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/DedicatedServer.java
@@ -18,6 +18,7 @@ import java.io.PrintStream;
import org.apache.logging.log4j.Level;
import org.bukkit.craftbukkit.LoggerOutputStream;
+import org.bukkit.craftbukkit.SpigotTimings; // Spigot
import org.bukkit.event.server.ServerCommandEvent;
// CraftBukkit end
@@ -317,6 +318,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer
}
public void aM() {
+ SpigotTimings.serverCommandTimer.startTiming(); // Spigot
while (!this.k.isEmpty()) {
ServerCommand servercommand = (ServerCommand) this.k.remove(0);
@@ -330,6 +332,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer
// CraftBukkit end
}
+ SpigotTimings.serverCommandTimer.stopTiming(); // Spigot
}
public boolean ad() {
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index ccf6479..c699dd1 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -16,6 +16,7 @@ import org.bukkit.entity.Hanging;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Painting;
import org.bukkit.entity.Vehicle;
+import org.spigotmc.CustomTimingsHandler; // Spigot
import org.bukkit.event.entity.EntityCombustByEntityEvent;
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
import org.bukkit.event.painting.PaintingBreakByEntityEvent;
@@ -112,6 +113,8 @@ public abstract class Entity implements ICommandListener {
public boolean valid; // CraftBukkit
public org.bukkit.projectiles.ProjectileSource projectileSource; // CraftBukkit - For projectiles only
+ public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getEntityTimings(this); // Spigot
+
public int getId() {
return this.id;
}
@@ -379,6 +382,8 @@ public abstract class Entity implements ICommandListener {
}
public void move(double d0, double d1, double d2) {
+ org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.startTiming(); // Spigot
+
if (this.T) {
this.a(this.getBoundingBox().c(d0, d1, d2));
this.recalcPosition();
@@ -715,6 +720,7 @@ public abstract class Entity implements ICommandListener {
this.world.methodProfiler.b();
}
+ org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.stopTiming(); // Spigot
}
private void recalcPosition() {
diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java
index d2a0954..71e1e6e 100644
--- a/src/main/java/net/minecraft/server/EntityLiving.java
+++ b/src/main/java/net/minecraft/server/EntityLiving.java
@@ -20,6 +20,8 @@ import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.vehicle.VehicleExitEvent;
// CraftBukkit end
+import org.bukkit.craftbukkit.SpigotTimings; // Spigot
+
public abstract class EntityLiving extends Entity {
private static final UUID a = UUID.fromString("662A6B8D-DA3E-4C1C-8813-96EA6097278D");
@@ -1397,6 +1399,7 @@ public abstract class EntityLiving extends Entity {
}
public void s_() {
+ SpigotTimings.timerEntityBaseTick.startTiming(); // Spigot
super.s_();
if (!this.world.isStatic) {
int i = this.bu();
@@ -1435,7 +1438,9 @@ public abstract class EntityLiving extends Entity {
}
}
+ SpigotTimings.timerEntityBaseTick.stopTiming(); // Spigot
this.m();
+ SpigotTimings.timerEntityTickRest.startTiming(); // Spigot
double d0 = this.locX - this.lastX;
double d1 = this.locZ - this.lastZ;
float f = (float) (d0 * d0 + d1 * d1);
@@ -1500,6 +1505,7 @@ public abstract class EntityLiving extends Entity {
this.world.methodProfiler.b();
this.aR += f2;
+ SpigotTimings.timerEntityTickRest.stopTiming(); // Spigot
}
protected float h(float f, float f1) {
@@ -1564,6 +1570,7 @@ public abstract class EntityLiving extends Entity {
}
this.world.methodProfiler.a("ai");
+ SpigotTimings.timerEntityAI.startTiming(); // Spigot
if (this.bC()) {
this.aW = false;
this.aX = 0.0F;
@@ -1574,6 +1581,7 @@ public abstract class EntityLiving extends Entity {
this.doTick();
this.world.methodProfiler.b();
}
+ SpigotTimings.timerEntityAI.stopTiming(); // Spigot
this.world.methodProfiler.b();
this.world.methodProfiler.a("jump");
@@ -1595,11 +1603,15 @@ public abstract class EntityLiving extends Entity {
this.aX *= 0.98F;
this.aY *= 0.98F;
this.aZ *= 0.9F;
+ SpigotTimings.timerEntityAIMove.startTiming(); // Spigot
this.g(this.aX, this.aY);
+ SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot
this.world.methodProfiler.b();
this.world.methodProfiler.a("push");
if (!this.world.isStatic) {
+ SpigotTimings.timerEntityAICollision.startTiming(); // Spigot
this.bK();
+ SpigotTimings.timerEntityAICollision.stopTiming(); // Spigot
}
this.world.methodProfiler.b();
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 392b895..072559e 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -45,6 +45,7 @@ import joptsimple.OptionSet;
import org.bukkit.craftbukkit.Main;
import org.bukkit.World.Environment;
+import org.bukkit.craftbukkit.SpigotTimings; // Spigot
import org.bukkit.craftbukkit.util.Waitable;
import org.bukkit.event.server.RemoteServerCommandEvent;
import org.bukkit.event.world.WorldSaveEvent;
@@ -585,6 +586,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs
protected void x() {}
protected void y() throws ExceptionWorldConflict { // CraftBukkit - added throws
+ SpigotTimings.serverTickTimer.startTiming(); // Spigot
long i = System.nanoTime();
++this.ticks;
@@ -611,10 +613,12 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs
}
if (autosavePeriod > 0 && this.ticks % autosavePeriod == 0) { // CraftBukkit
+ SpigotTimings.worldSaveTimer.startTiming(); // Spigot
this.methodProfiler.a("save");
this.v.savePlayers();
this.saveChunks(true);
this.methodProfiler.b();
+ SpigotTimings.worldSaveTimer.stopTiming(); // Spigot
}
this.methodProfiler.a("tallying");
@@ -631,6 +635,8 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs
this.methodProfiler.b();
this.methodProfiler.b();
+ SpigotTimings.serverTickTimer.stopTiming(); // Spigot
+ org.spigotmc.CustomTimingsHandler.tick(); // Spigot
}
public void z() {
@@ -653,16 +659,23 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs
this.methodProfiler.c("levels");
+ SpigotTimings.schedulerTimer.startTiming(); // Spigot
// CraftBukkit start
this.server.getScheduler().mainThreadHeartbeat(this.ticks);
+ SpigotTimings.schedulerTimer.stopTiming(); // Spigot
// Run tasks that are waiting on processing
+ SpigotTimings.processQueueTimer.startTiming(); // Spigot
while (!processQueue.isEmpty()) {
processQueue.remove().run();
}
+ SpigotTimings.processQueueTimer.stopTiming(); // Spigot
+ SpigotTimings.chunkIOTickTimer.startTiming(); // Spigot
org.bukkit.craftbukkit.chunkio.ChunkIOExecutor.tick();
+ SpigotTimings.chunkIOTickTimer.stopTiming(); // Spigot
+ SpigotTimings.timeUpdateTimer.startTiming(); // Spigot
// Send time updates to everyone, it will get the right time from the world the player is in.
if (this.ticks % 20 == 0) {
for (int i = 0; i < this.getPlayerList().players.size(); ++i) {
@@ -670,6 +683,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs
entityplayer.playerConnection.sendPacket(new PacketPlayOutUpdateTime(entityplayer.world.getTime(), entityplayer.getPlayerTime(), entityplayer.world.getGameRules().getBoolean("doDaylightCycle"))); // Add support for per player time
}
}
+ SpigotTimings.timeUpdateTimer.stopTiming(); // Spigot
int i;
@@ -693,7 +707,9 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs
CrashReport crashreport;
try {
+ worldserver.timings.doTick.startTiming(); // Spigot
worldserver.doTick();
+ worldserver.timings.doTick.stopTiming(); // Spigot
} catch (Throwable throwable1) {
crashreport = CrashReport.a(throwable1, "Exception ticking world");
worldserver.a(crashreport);
@@ -701,7 +717,9 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs
}
try {
+ worldserver.timings.tickEntities.startTiming(); // Spigot
worldserver.tickEntities();
+ worldserver.timings.tickEntities.stopTiming(); // Spigot
} catch (Throwable throwable2) {
crashreport = CrashReport.a(throwable2, "Exception ticking world entities");
worldserver.a(crashreport);
@@ -710,7 +728,9 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs
this.methodProfiler.b();
this.methodProfiler.a("tracker");
+ worldserver.timings.tracker.startTiming(); // Spigot
worldserver.getTracker().updatePlayers();
+ worldserver.timings.tracker.stopTiming(); // Spigot
this.methodProfiler.b();
this.methodProfiler.b();
// } // CraftBukkit
@@ -719,14 +739,20 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs
}
this.methodProfiler.c("connection");
+ SpigotTimings.connectionTimer.startTiming(); // Spigot
this.ao().c();
+ SpigotTimings.connectionTimer.stopTiming(); // Spigot
this.methodProfiler.c("players");
+ SpigotTimings.playerListTimer.startTiming(); // Spigot
this.v.tick();
+ SpigotTimings.playerListTimer.stopTiming(); // Spigot
this.methodProfiler.c("tickables");
+ SpigotTimings.tickablesTimer.startTiming(); // Spigot
for (i = 0; i < this.o.size(); ++i) {
((IUpdatePlayerListBox) this.o.get(i)).c();
}
+ SpigotTimings.tickablesTimer.stopTiming(); // Spigot
this.methodProfiler.b();
}
diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
index 2d8ad1c..3727214 100644
--- a/src/main/java/net/minecraft/server/PlayerConnection.java
+++ b/src/main/java/net/minecraft/server/PlayerConnection.java
@@ -1042,6 +1042,8 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
// CraftBukkit end
private void handleCommand(String s) {
+ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.startTiming(); // Spigot
+
// CraftBukkit start - whole method
this.c.info(this.player.getName() + " issued server command: " + s);
@@ -1051,18 +1053,22 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
this.server.getPluginManager().callEvent(event);
if (event.isCancelled()) {
+ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot
return;
}
try {
if (this.server.dispatchCommand(event.getPlayer(), event.getMessage().substring(1))) {
+ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot
return;
}
} catch (org.bukkit.command.CommandException ex) {
player.sendMessage(org.bukkit.ChatColor.RED + "An internal error occurred while attempting to perform this command");
java.util.logging.Logger.getLogger(PlayerConnection.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
+ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot
return;
}
+ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot
// this.minecraftServer.getCommandHandler().a(this.player, s);
// CraftBukkit end
}
diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java
index ec76148..a93ad27 100644
--- a/src/main/java/net/minecraft/server/TileEntity.java
+++ b/src/main/java/net/minecraft/server/TileEntity.java
@@ -6,10 +6,12 @@ import java.util.concurrent.Callable;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.spigotmc.CustomTimingsHandler; // Spigot
import org.bukkit.inventory.InventoryHolder; // CraftBukkit
public abstract class TileEntity {
+ public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot
private static final Logger a = LogManager.getLogger();
private static Map f = Maps.newHashMap();
private static Map g = Maps.newHashMap();
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 86be044..06bd661 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -18,6 +18,7 @@ import org.bukkit.Bukkit;
import org.bukkit.block.BlockState;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.craftbukkit.util.LongHashSet;
+import org.bukkit.craftbukkit.SpigotTimings; // Spigot
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.CraftWorld;
@@ -125,6 +126,8 @@ public abstract class World implements IBlockAccess {
public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot
+ public final SpigotTimings.WorldTimingsHandler timings; // Spigot
+
public CraftWorld getWorld() {
return this.world;
}
@@ -164,6 +167,7 @@ public abstract class World implements IBlockAccess {
this.M.a(new WorldBorderListener(((WorldServer) this).getServer().getHandle())); // CraftBukkit
this.getServer().addWorld(this.world); // CraftBukkit
+ timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings
}
public World b() {
@@ -1254,6 +1258,7 @@ public abstract class World implements IBlockAccess {
this.g.clear();
this.methodProfiler.c("regular");
+ timings.entityTick.startTiming(); // Spigot
// CraftBukkit start - Use field for loop variable
for (this.tickPosition = 0; this.tickPosition < this.entityList.size(); ++this.tickPosition) {
entity = (Entity) this.entityList.get(this.tickPosition);
@@ -1270,7 +1275,9 @@ public abstract class World implements IBlockAccess {
this.methodProfiler.a("tick");
if (!entity.dead) {
try {
+ SpigotTimings.tickEntityTimer.startTiming(); // Spigot
this.g(entity);
+ SpigotTimings.tickEntityTimer.stopTiming(); // Spigot
} catch (Throwable throwable1) {
crashreport = CrashReport.a(throwable1, "Ticking entity");
crashreportsystemdetails = crashreport.a("Entity being ticked");
@@ -1295,7 +1302,9 @@ public abstract class World implements IBlockAccess {
this.methodProfiler.b();
}
+ timings.entityTick.stopTiming(); // Spigot
this.methodProfiler.c("blockEntities");
+ timings.tileEntityTick.startTiming(); // Spigot
this.L = true;
// CraftBukkit start - From below, clean up tile entities before ticking them
if (!this.b.isEmpty()) {
@@ -1315,6 +1324,7 @@ public abstract class World implements IBlockAccess {
if (this.isLoaded(blockposition) && this.M.a(blockposition)) {
try {
+ tileentity.tickTimer.startTiming(); // Spigot
((IUpdatePlayerListBox) tileentity).c();
} catch (Throwable throwable2) {
CrashReport crashreport1 = CrashReport.a(throwable2, "Ticking block entity");
@@ -1323,6 +1333,11 @@ public abstract class World implements IBlockAccess {
tileentity.a(crashreportsystemdetails1);
throw new ReportedException(crashreport1);
}
+ // Spigot start
+ finally {
+ tileentity.tickTimer.stopTiming();
+ }
+ // Spigot end
}
}
@@ -1335,6 +1350,8 @@ public abstract class World implements IBlockAccess {
}
}
+ timings.tileEntityTick.stopTiming(); // Spigot
+ timings.tileEntityPending.startTiming(); // Spigot
this.L = false;
/* CraftBukkit start - Moved up
if (!this.b.isEmpty()) {
@@ -1367,6 +1384,7 @@ public abstract class World implements IBlockAccess {
this.a.clear();
}
+ timings.tileEntityPending.stopTiming(); // Spigot
this.methodProfiler.b();
this.methodProfiler.b();
}
@@ -1411,6 +1429,7 @@ public abstract class World implements IBlockAccess {
// CraftBukkit start - Use neighbor cache instead of looking up
Chunk startingChunk = this.getChunkIfLoaded(i >> 4, j >> 4);
if (!flag || (startingChunk != null && startingChunk.areNeighborsLoaded(2)) /* this.isAreaLoaded(i - b0, 0, j - b0, i + b0, 0, j + b0) */) {
+ entity.tickTimer.startTiming(); // Spigot
// CraftBukkit end
entity.P = entity.locX;
entity.Q = entity.locY;
@@ -1474,6 +1493,7 @@ public abstract class World implements IBlockAccess {
}
}
+ entity.tickTimer.stopTiming(); // Spigot
}
}
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 8a09a79..1d6be5f 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -210,10 +210,13 @@ public class WorldServer extends World implements IAsyncTaskHandler {
// CraftBukkit start - Only call spawner if we have players online and the world allows for mobs or animals
long time = this.worldData.getTime();
if (this.getGameRules().getBoolean("doMobSpawning") && this.worldData.getType() != WorldType.DEBUG_ALL_BLOCK_STATES && (this.allowMonsters || this.allowAnimals) && (this instanceof WorldServer && this.players.size() > 0)) {
+ timings.mobSpawn.startTiming(); // Spigot
this.R.a(this, this.allowMonsters && (this.ticksPerMonsterSpawns != 0 && time % this.ticksPerMonsterSpawns == 0L), this.allowAnimals && (this.ticksPerAnimalSpawns != 0 && time % this.ticksPerAnimalSpawns == 0L), this.worldData.getTime() % 400L == 0L);
+ timings.mobSpawn.stopTiming(); // Spigot
// CraftBukkit end
}
-
+ // CraftBukkit end
+ timings.doChunkUnload.startTiming(); // Spigot
this.methodProfiler.c("chunkSource");
this.chunkProvider.unloadChunks();
int j = this.a(1.0F);
@@ -227,21 +230,34 @@ public class WorldServer extends World implements IAsyncTaskHandler {
this.worldData.setDayTime(this.worldData.getDayTime() + 1L);
}
+ timings.doChunkUnload.stopTiming(); // Spigot
this.methodProfiler.c("tickPending");
+ timings.doTickPending.startTiming(); // Spigot
this.a(false);
+ timings.doTickPending.stopTiming(); // Spigot
this.methodProfiler.c("tickBlocks");
+ timings.doTickTiles.startTiming(); // Spigot
this.h();
+ timings.doTickTiles.stopTiming(); // Spigot
this.methodProfiler.c("chunkMap");
+ timings.doChunkMap.startTiming(); // Spigot
this.manager.flush();
+ timings.doChunkMap.stopTiming(); // Spigot
this.methodProfiler.c("village");
+ timings.doVillages.startTiming(); // Spigot
this.villages.tick();
this.siegeManager.a();
+ timings.doVillages.stopTiming(); // Spigot
this.methodProfiler.c("portalForcer");
+ timings.doPortalForcer.startTiming(); // Spigot
this.Q.a(this.getTime());
+ timings.doPortalForcer.stopTiming(); // Spigot
this.methodProfiler.b();
+ timings.doSounds.startTiming(); // Spigot
this.ak();
this.getWorld().processChunkGC(); // CraftBukkit
+ timings.doChunkGC.stopTiming(); // Spigot
}
public BiomeMeta a(EnumCreatureType enumcreaturetype, BlockPosition blockposition) {
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index 09c723f..07f15d1 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1638,6 +1638,11 @@ public final class CraftServer implements Server {
private final Spigot spigot = new Spigot()
{
+ @Override
+ public YamlConfiguration getConfig()
+ {
+ return org.spigotmc.SpigotConfig.config;
+ }
};
public Spigot spigot()
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index faefbe7..8105872 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -255,9 +255,11 @@ public class CraftWorld implements World {
net.minecraft.server.Chunk chunk = world.chunkProviderServer.chunks.get(LongHash.toLong(x, z));
if (chunk == null) {
+ world.timings.syncChunkLoadTimer.startTiming(); // Spigot
chunk = world.chunkProviderServer.loadChunk(x, z);
chunkLoadPostProcess(chunk, x, z);
+ world.timings.syncChunkLoadTimer.stopTiming(); // Spigot
}
return chunk != null;
}
diff --git a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java
new file mode 100644
index 0000000..558574f
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java
@@ -0,0 +1,170 @@
+package org.bukkit.craftbukkit;
+
+import com.google.common.collect.Maps;
+import net.minecraft.server.*;
+import org.bukkit.plugin.java.JavaPluginLoader;
+import org.spigotmc.CustomTimingsHandler;
+import org.bukkit.scheduler.BukkitTask;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.bukkit.craftbukkit.scheduler.CraftTask;
+
+public class SpigotTimings {
+
+ public static final CustomTimingsHandler serverTickTimer = new CustomTimingsHandler("** Full Server Tick");
+ public static final CustomTimingsHandler playerListTimer = new CustomTimingsHandler("Player List");
+ public static final CustomTimingsHandler connectionTimer = new CustomTimingsHandler("Connection Handler");
+ public static final CustomTimingsHandler tickablesTimer = new CustomTimingsHandler("Tickables");
+ public static final CustomTimingsHandler schedulerTimer = new CustomTimingsHandler("Scheduler");
+ public static final CustomTimingsHandler chunkIOTickTimer = new CustomTimingsHandler("ChunkIOTick");
+ public static final CustomTimingsHandler timeUpdateTimer = new CustomTimingsHandler("Time Update");
+ public static final CustomTimingsHandler serverCommandTimer = new CustomTimingsHandler("Server Command");
+ public static final CustomTimingsHandler worldSaveTimer = new CustomTimingsHandler("World Save");
+
+ public static final CustomTimingsHandler entityMoveTimer = new CustomTimingsHandler("** entityMove");
+ public static final CustomTimingsHandler tickEntityTimer = new CustomTimingsHandler("** tickEntity");
+ public static final CustomTimingsHandler activatedEntityTimer = new CustomTimingsHandler("** activatedTickEntity");
+ public static final CustomTimingsHandler tickTileEntityTimer = new CustomTimingsHandler("** tickTileEntity");
+
+ public static final CustomTimingsHandler timerEntityBaseTick = new CustomTimingsHandler("** livingEntityBaseTick");
+ public static final CustomTimingsHandler timerEntityAI = new CustomTimingsHandler("** livingEntityAI");
+ public static final CustomTimingsHandler timerEntityAICollision = new CustomTimingsHandler("** livingEntityAICollision");
+ public static final CustomTimingsHandler timerEntityAIMove = new CustomTimingsHandler("** livingEntityAIMove");
+ public static final CustomTimingsHandler timerEntityTickRest = new CustomTimingsHandler("** livingEntityTickRest");
+
+ public static final CustomTimingsHandler processQueueTimer = new CustomTimingsHandler("processQueue");
+ public static final CustomTimingsHandler schedulerSyncTimer = new CustomTimingsHandler("** Scheduler - Sync Tasks", JavaPluginLoader.pluginParentTimer);
+
+ public static final CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("** playerCommand");
+
+ public static final HashMap<String, CustomTimingsHandler> entityTypeTimingMap = new HashMap<String, CustomTimingsHandler>();
+ public static final HashMap<String, CustomTimingsHandler> tileEntityTypeTimingMap = new HashMap<String, CustomTimingsHandler>();
+ public static final HashMap<String, CustomTimingsHandler> pluginTaskTimingMap = new HashMap<String, CustomTimingsHandler>();
+
+ /**
+ * Gets a timer associated with a plugins tasks.
+ * @param task
+ * @param period
+ * @return
+ */
+ public static CustomTimingsHandler getPluginTaskTimings(BukkitTask task, long period) {
+ if (!task.isSync()) {
+ return null;
+ }
+ String plugin;
+ final CraftTask ctask = (CraftTask) task;
+
+ if (task.getOwner() != null) {
+ plugin = task.getOwner().getDescription().getFullName();
+ } else if (ctask.timingName != null) {
+ plugin = "CraftScheduler";
+ } else {
+ plugin = "Unknown";
+ }
+ String taskname = ctask.getTaskName();
+
+ String name = "Task: " + plugin + " Runnable: " + taskname;
+ if (period > 0) {
+ name += "(interval:" + period +")";
+ } else {
+ name += "(Single)";
+ }
+ CustomTimingsHandler result = pluginTaskTimingMap.get(name);
+ if (result == null) {
+ result = new CustomTimingsHandler(name, SpigotTimings.schedulerSyncTimer);
+ pluginTaskTimingMap.put(name, result);
+ }
+ return result;
+ }
+
+ /**
+ * Get a named timer for the specified entity type to track type specific timings.
+ * @param entity
+ * @return
+ */
+ public static CustomTimingsHandler getEntityTimings(Entity entity) {
+ String entityType = entity.getClass().getSimpleName();
+ CustomTimingsHandler result = entityTypeTimingMap.get(entityType);
+ if (result == null) {
+ result = new CustomTimingsHandler("** tickEntity - " + entityType, activatedEntityTimer);
+ entityTypeTimingMap.put(entityType, result);
+ }
+ return result;
+ }
+
+ /**
+ * Get a named timer for the specified tile entity type to track type specific timings.
+ * @param entity
+ * @return
+ */
+ public static CustomTimingsHandler getTileEntityTimings(TileEntity entity) {
+ String entityType = entity.getClass().getSimpleName();
+ CustomTimingsHandler result = tileEntityTypeTimingMap.get(entityType);
+ if (result == null) {
+ result = new CustomTimingsHandler("** tickTileEntity - " + entityType, tickTileEntityTimer);
+ tileEntityTypeTimingMap.put(entityType, result);
+ }
+ return result;
+ }
+
+ /**
+ * Set of timers per world, to track world specific timings.
+ */
+ public static class WorldTimingsHandler {
+ public final CustomTimingsHandler mobSpawn;
+ public final CustomTimingsHandler doChunkUnload;
+ public final CustomTimingsHandler doPortalForcer;
+ public final CustomTimingsHandler doTickPending;
+ public final CustomTimingsHandler doTickTiles;
+ public final CustomTimingsHandler doVillages;
+ public final CustomTimingsHandler doChunkMap;
+ public final CustomTimingsHandler doChunkGC;
+ public final CustomTimingsHandler doSounds;
+ public final CustomTimingsHandler entityTick;
+ public final CustomTimingsHandler tileEntityTick;
+ public final CustomTimingsHandler tileEntityPending;
+ public final CustomTimingsHandler tracker;
+ public final CustomTimingsHandler doTick;
+ public final CustomTimingsHandler tickEntities;
+
+ public final CustomTimingsHandler syncChunkLoadTimer;
+ public final CustomTimingsHandler syncChunkLoadDataTimer;
+ public final CustomTimingsHandler syncChunkLoadStructuresTimer;
+ public final CustomTimingsHandler syncChunkLoadEntitiesTimer;
+ public final CustomTimingsHandler syncChunkLoadTileEntitiesTimer;
+ public final CustomTimingsHandler syncChunkLoadTileTicksTimer;
+ public final CustomTimingsHandler syncChunkLoadPostTimer;
+
+ public WorldTimingsHandler(World server) {
+ String name = server.worldData.getName() +" - ";
+
+ mobSpawn = new CustomTimingsHandler("** " + name + "mobSpawn");
+ doChunkUnload = new CustomTimingsHandler("** " + name + "doChunkUnload");
+ doTickPending = new CustomTimingsHandler("** " + name + "doTickPending");
+ doTickTiles = new CustomTimingsHandler("** " + name + "doTickTiles");
+ doVillages = new CustomTimingsHandler("** " + name + "doVillages");
+ doChunkMap = new CustomTimingsHandler("** " + name + "doChunkMap");
+ doSounds = new CustomTimingsHandler("** " + name + "doSounds");
+ doChunkGC = new CustomTimingsHandler("** " + name + "doChunkGC");
+ doPortalForcer = new CustomTimingsHandler("** " + name + "doPortalForcer");
+ entityTick = new CustomTimingsHandler("** " + name + "entityTick");
+ tileEntityTick = new CustomTimingsHandler("** " + name + "tileEntityTick");
+ tileEntityPending = new CustomTimingsHandler("** " + name + "tileEntityPending");
+
+ syncChunkLoadTimer = new CustomTimingsHandler("** " + name + "syncChunkLoad");
+ syncChunkLoadDataTimer = new CustomTimingsHandler("** " + name + "syncChunkLoad - Data");
+ syncChunkLoadStructuresTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Structures");
+ syncChunkLoadEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Entities");
+ syncChunkLoadTileEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileEntities");
+ syncChunkLoadTileTicksTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileTicks");
+ syncChunkLoadPostTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Post");
+
+
+ tracker = new CustomTimingsHandler(name + "tracker");
+ doTick = new CustomTimingsHandler(name + "doTick");
+ tickEntities = new CustomTimingsHandler(name + "tickEntities");
+ }
+ }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java
index 26ea0d3..7fabfa3 100644
--- a/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java
+++ b/src/main/java/org/bukkit/craftbukkit/chunkio/ChunkIOProvider.java
@@ -40,7 +40,9 @@ class ChunkIOProvider implements AsynchronousExecutor.CallBackProvider<QueuedChu
chunk.addEntities();
if (queuedChunk.provider.chunkProvider != null) {
+ queuedChunk.provider.world.timings.syncChunkLoadStructuresTimer.startTiming(); // Spigot
queuedChunk.provider.chunkProvider.recreateStructures(chunk, queuedChunk.x, queuedChunk.z);
+ queuedChunk.provider.world.timings.syncChunkLoadStructuresTimer.stopTiming(); // Spigot
}
Server server = queuedChunk.provider.world.getServer();
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
index 9fea4fb..8442ecb 100644
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
@@ -346,7 +346,9 @@ public class CraftScheduler implements BukkitScheduler {
}
if (task.isSync()) {
try {
+ task.timings.startTiming(); // Spigot
task.run();
+ task.timings.stopTiming(); // Spigot
} catch (final Throwable throwable) {
task.getOwner().getLogger().log(
Level.WARNING,
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java
index 55db3ff..220e39a 100644
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java
@@ -1,11 +1,13 @@
package org.bukkit.craftbukkit.scheduler;
import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.SpigotTimings; // Spigot
+import org.spigotmc.CustomTimingsHandler; // Spigot
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitTask;
-class CraftTask implements BukkitTask, Runnable {
+public class CraftTask implements BukkitTask, Runnable { // Spigot
private volatile CraftTask next = null;
/**
@@ -22,6 +24,7 @@ class CraftTask implements BukkitTask, Runnable {
private final Plugin plugin;
private final int id;
+ final CustomTimingsHandler timings; // Spigot
CraftTask() {
this(null, null, -1, -1);
}
@@ -30,11 +33,26 @@ class CraftTask implements BukkitTask, Runnable {
this(null, task, -1, -1);
}
- CraftTask(final Plugin plugin, final Runnable task, final int id, final long period) {
+ // Spigot start
+ public String timingName = null;
+ CraftTask(String timingName) {
+ this(timingName, null, null, -1, -1);
+ }
+ CraftTask(String timingName, final Runnable task) {
+ this(timingName, null, task, -1, -1);
+ }
+ CraftTask(String timingName, final Plugin plugin, final Runnable task, final int id, final long period) {
this.plugin = plugin;
this.task = task;
this.id = id;
this.period = period;
+ this.timingName = timingName == null && task == null ? "Unknown" : timingName;
+ timings = this.isSync() ? SpigotTimings.getPluginTaskTimings(this, period) : null;
+ }
+
+ CraftTask(final Plugin plugin, final Runnable task, final int id, final long period) {
+ this(null, plugin, task, id, period);
+ // Spigot end
}
public final int getTaskId() {
@@ -94,4 +112,13 @@ class CraftTask implements BukkitTask, Runnable {
setPeriod(-2l);
return true;
}
+
+ // Spigot start
+ public String getTaskName() {
+ if (timingName != null) {
+ return timingName;
+ }
+ return task.getClass().getName();
+ }
+ // Spigot end
}
--
2.1.0